分割回文串
回文串(palindrome string):指一个镜像对称的字符串
- abba
- a
- asdsa
但如果一个字符串并不是回文串,它可以被视为是一系列回文串的组合:
- aab = aa + b
- asdf = a + s + d + f
- add = a + dd
现在我们要解决:对于一个字符串,其最少要分割几次才能使得得到的子串都是回文串?
我们可以运用递推的方法,来得到一个长为n的串需要分割几次才能全部分割成回文串:
如果记函数f(j)表示前j个字符形成的子串的最小分割数(比如字符串“1234321”的f(6) 为1,会分成“1”、“23432”
则我们要求的就是f(n)
如果这个长为n的串,本身就是一个回文串,则f(n) = 0
如果不是:
- 可以视为长为n-1的字符串后面又添了一个字符,要比长为n-1的串多分割一次,即f(n) = f(n-1) + 1
- 可能存在某种情况,即从第i个字符到第n个字符是回文串,此时f(n) = f(i-1) + 1
要从这两种情况中取到最小的分割数
至于判断是否是回文串,我在代码中的注释中写出,如下:
If we want to know how many times we would cut, we need to know the situation of palindrome in this string.
That is, we need to know if any of its segments is palindrome string.
Now, we have following ways to judge:1. just contain one char 2. just contain two chars and they are equal 3. more than three chars and satisfy these following conditions: the subString from the second char to the next-to-last char is a palindrome string the first and the last char are equal
下面是代码:
int minCut(string s) {
int length = s.length();
// if we want to know how many times we would cut, we need to know the situation of palindrome in this string
// we need to know if any of its segments is palindrome string
// we have following ways to judge
// 1. just contain one char
// 2. just contain two chars and they are equal
// 3. more than three chars and satisfy these following conditions:
// the subString from the second char to the next-to-last char is a palindrome string
// the first and the last char are equal
vector<vector<bool>> palindromic(length, vector<bool>(length));
for(int i = 0 ; i < length ; i++){
for(int j = i ; j >= 0 ; j--){
if(i == j){
palindromic[j][i] = true;
}else if(i - j == 1){
if(s[i] == s[j]){
palindromic[j][i] = true;
}
}else{
if(s[i] == s[j] && palindromic[j+1][i-1]){
palindromic[j][i] = true;
}else{
palindromic[j][i] = false;
}
}
}
}
vector<int> cutTimes(length);
for(int i = 0 ; i < length ; i ++){
if(palindromic[0][i])cutTimes[i] = 0;
else{
cutTimes[i] = cutTimes[i - 1] + 1;
for(int j = 1 ; j < i ; j++){
if(palindromic[j][i])
cutTimes[i] = cutTimes[j - 1] + 1 < cutTimes[i] ? cutTimes[j - 1] + 1 : cutTimes[i];
}
}
}
return cutTimes[length - 1];
}
时间复杂度和空间复杂度皆为O(n²)