/* 在求最长回文子串时,如果暴力枚举左右端点,将得到指数级的复杂度。优化一点,使用二维数组来DP,可以将复杂度降到O(m*n)m,n为两条串的长度。本文采用Manacher算法,无论是时间还是空间上都优于二维DP。 */
1 #include <iostream> 2 #include <string> 3 #define Maxsize 100 4 using namespace std; 5 int Len[Maxsize]; 6 int main(){ 7 string pre; 8 cin >> pre; 9 string tool = "{"; // 防止越界。 10 int len = (int)pre.length(); 11 for(int i = 0; i < len; i++){ 12 tool+="#"; 13 tool+=pre[i]; 14 } 15 tool+="#"; 16 tool+="}"; // 防止越界 17 int mx = 0,ans = 0,po = 0; 18 int len2 = (int)tool.length(); 19 for(int i = 1; i < len2; i++){ 20 /* 选取下界 */ 21 if(mx > i) 22 Len[i] = min(mx-i,Len[2*po-i]); 23 else 24 Len[i] = 1; 25 /* 判断上界 */ 26 /* 注意,无论是哪一种情况,算法都无法保证新计算的回文串长度小于某一个上界,只有可能得出 27 其下界。算法主要简化的部分就是避免了重复判断下界的过程。而对于某一个回文子串是否可 28 以更长是不得而知的,因此必须额外判断。 */ 29 while(tool[i-Len[i]] == tool[i+Len[i]]) 30 Len[i]++; 31 /* 判断是否需要更新 最右回文串端点 、 答案 */ 32 if(Len[i] + i > mx){ 33 mx = Len[i] + i; 34 po = i; 35 } 36 ans = max(ans,Len[i]); 37 } 38 cout<<ans-1; 39 return 0; 40 }
Manacher 算法,以O( n )的复杂度判断出回文子串的最大长度。
具体原理及证明过程请参考以下两篇博客: