Manacher算法 求最长回文串
len[i] 表示以 i 为中心的最长回文串长度,pos 储存目前右边界最大的回文串中心, mx为右边界。
当 i 小于 mx 时,那么以 i 为中心的回文串有三种可能的情况:
1、len[2 * pos - i] 如果小于 mx,则 len[i] = len[2 * pos - i];
2、len[2 * pos - i] 如果大于 mx,则 len[i] = mx - i;
3、len[2 * pos - i] 如果等于 mx,则 len[i] = len[2 * pos - i],然后再向左右扩展循环判断是否一致,如果一致 len[i]++;
当 i 大于等于 mx 时,就无法通过已知的数据求解 len[i],只能令 len[i] 先等于 1,然后向左右扩展求解
其中为了保证判断的回文串是奇回文串,要在每个元素中间和整个字符串的左右插入一个不常用字符 '#'
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int len[10000];
string manacher(string a){
string str = "#";
for(int i=0; i < a.size(); i++)
str = str + a[i] + '#';
int str_len = str.size();
int mx = 0, pos = 0, mlen = 0, ans = 0;
for(int i=0; i < str_len; i++){
if(i < mx) len[i] = min(mx - i, len[2*pos - i]);
else len[i] = 1;
while(i-len[i] >= 0 && i+len[i] < str_len && str[i-len[i]] == str[i+len[i]]) len[i]++;
if(len[i]+i > mx){
mx = len[i] + i;
pos = i;
if(mlen < len[i]){
mlen = len[i];
ans = i;
}
}
}
string res = "";
for(int i=ans-mlen+1; i < ans+mlen; i++)
if(str[i] != '#') res = res + str[i];
return res;
}
int main(){
string str;
while(cin >> str){
cout << manacher(str) << endl;
}
return 0;
}