-
Notifications
You must be signed in to change notification settings - Fork 307
/
Copy pathMPC.java
169 lines (129 loc) · 4.74 KB
/
MPC.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
//Given a string, a partitioning of the string is a palindrome partitioning
//if every substring of the partition is a palindrome. For example,
//“aba|b|bbabb|a|b|aba” is a palindrome partitioning of “ababbbabbababa”.
//Determine the fewest cuts needed for palindrome partitioning of a given
//string. This is a DP problem.
// Author - Aastha Aneja (Github handle - Aashu24)
// Email - anejaaastha@gmail.com
import java.util.Scanner;
public class MPC {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
System.out.println("Enter a string:");
// input string
String str = in.next();
// required function call
System.out.println(findMpc(str));
}
// This function returns the minimum number of partitions required to divide a
// string in such a way that all its parts become planidromes
public static int findMpc(String str) {
// This array will store true if the substring starting from i to j is a
// palindrome in palinres[i][j]
boolean[][] palinres = new boolean[str.length()][str.length()];
// we fill this 2d matrix diagonally by using gap variable, gap represents gap
// between i and j
for (int gap = 0; gap < str.length(); ++gap) {
// initially i will be 0 and j will be i+gap
int i = 0, j = i + gap;
// we will iterate till j doesn't go out of bounds
while (j < str.length()) {
// if gap is 0, it means that the length of the substring is 1 and a string of
// length 1 is always a palindrome
if (gap == 0) {
// so we put true
palinres[i][j] = true;
}
// if gap is 1, it means length of substring is 2 and a string of length 2 is a
// plaindrome if both its characters are same
else if (gap == 1) {
// this will put true if characters are same and false if characters are
// different
palinres[i][j] = str.charAt(i) == str.charAt(j);
}
// if length is more than 2, we check if the first and last characters are same
// and if the rest of the string in the middle is a palindromes
else {
palinres[i][j] = str.charAt(i) == str.charAt(j) && palinres[i + 1][j - 1];
}
// increment i
i++;
// increment j
j++;
}
}
// This matrix will store the minimum number of partitions required to make all
// parts palindromes for a string from i to j
int[][] mpc = new int[str.length()][str.length()];
// we iterate over this matrix similarly using gap variable diagonally
for (int gap = 0; gap < str.length(); ++gap) {
// initially i=0 and j=gap+i
int i = 0, j = i + gap;
// we will iterate till j doesn't go out of bounds
while (j < str.length()) {
// if gap is 0, it means that the length of the substring is 1 and a string of
// length 1 is always a palindrome
if (gap == 0) {
// so min no. of cuts is 0
mpc[i][j] = 0;
}
// if gap is 1, it means length of substring is 2 and a string of length 2 is a
// plaindrome if both its characters are same
else if (gap == 1) {
// and the string is a palindrome
if (palinres[i][j])
// min no. of cuts required will be 0
mpc[i][j] = 0;
else
// min no. of cuts required is 1
mpc[i][j] = 1;
}
// if length is more than 2
else {
// and if the string is a palindrome
if (palinres[i][j]) {
// min no. of cuts required is 0
mpc[i][j] = 0;
// increment i and j
i++;
j++;
// and continue to next iteration
continue;
}
// if the string is not a palindrome, we need to find minimum no. of cuts for it
int minValue = Integer.MAX_VALUE;
// we try and divide the string into halves by putting a cut at every possible
// position and choose the one that gives us min no. of cuts
for (int cut = i; cut < j; ++cut) {
// first part of string after cut
int fp = mpc[i][cut];
// second part of string after cut
int sp = mpc[cut + 1][j];
// factor is the minimum no. of cuts for whole string which will be cuts for fp
// + cuts for sp + 1(to divide string into fp and sp)
int factor = fp + sp + 1;
// if this factor is less than overall min cuts
if (factor < minValue) {
// we update minValue
minValue = factor;
}
}
// finally we put the minValue in mpc[i][j]
mpc[i][j] = minValue;
}
// increment i and j
i++;
j++;
}
}
// the ans will be stored in mpc[0][str.length()-1]
return mpc[0][str.length() - 1];
}
}
// Time complexity analysis -
// The time complexity of the function will be O(n^2) as we have to fill the
// whole 2d matrix for palinres and mpc.
// Space complexity analysis -
// The extra space used by this algorithm is O(n^2) as we made two 2d matrices
// palinres and mpc.