思路筆記:
上述情況1和情況2又可以歸結爲:【i’的迴文半徑】和【R-i的距離】中小的那個就是i的迴文半徑。
#include<iostream>
#include<stack>
#include<string>
using namespace std;
string manacherString(string str) {
string res = "";
int index = 0;
for (int i = 0; i != 2*str.length()+1; ++i) {//偶數位置就是以0結尾的i&1就是偶數部分,i遞增,i&1就是求0,2,4,6,8...
(i & 1) == 0 ? res+="#" : res+=str[index++];
}
return res;
}
int min(int a, int b) {
return a < b ? a : b;
}
int max(int a, int b) {
return a > b ? a : b;
}
int manacher(string str) {
if (str.length() == 0)
return 0;
string newStr = manacherString(str);
int pArr_len = newStr.length();
int *pArr = new int[pArr_len];//pArr會問半徑數組
int C = -1;//中心點從-1開始
int R = -1;
int MAX = INT_MIN;
for (int i = 0; i != newStr.length(); ++i) {
if (R > i)//i在R邊界內
pArr[i] = min(pArr[2 * C - i], R - i);
else
pArr[i] = 1;//i在R邊界外
while (i + pArr[i]<pArr_len && i - pArr[i]>-1) {//繼續往下擴,保證擴出來不越界就可以了
if (newStr[i + pArr[i]] == newStr[i - pArr[i]])
pArr[i]++;
else
break;
}
if (i + pArr[i] > R) {
R = i + pArr[i];//最右迴文右邊界更新爲i+pArr[i]
C = i;
}
MAX = max(MAX, pArr[i]);
}
return MAX-1;
}
int main() {
string str;
while (cin >> str) {
cout << manacherString(str) << endl;
cout << manacher(str) << endl;
}
return 0;
}
應用:如果向字符串後面追加字符串成爲迴文串,怎麼添加的字符最少。
例子:abc12321,則添加後abc12321cba
思路:它就是在求包含最後一個字符情況下最長迴文串是多少,再將前面不是的部分逆序過來就是答案。其實就是在找回文右邊界(R),直到迴文右邊界到最後一個字符確定當前的C,利用R將L求出來,然後原字符串0~L位置的逆序追加上去即可。