您的位置:首页 > 其它

最长回文串 Manacher

2017-07-10 16:00 155 查看
复杂度O(n)

Manacher’s ALGORITHM: O(n)时间求字符串的最长回文子串

#include <bits/stdc++.h>

using namespace std;

const int MAXN = 1E6;
int p[MAXN*2];//p[i]:=转换后的字符串以t[i]为中心的回文串一侧长度+1(中心)
char s[MAXN];
char t[MAXN*2];//装换后的字符
//abac转换后
//$#a#b#c#\0

//以原字符串第i个字符为中心的最长回文串总长度 = p[i*2+2] - 1;
//以s[i]和s[i+1]中间为中心的最长回文串总长度 = p[i*2+3]

void manacher()
{
int len = strlen(s);
t[0] = '$';
t[1] = '#';
for(int i=0; i<len; ++i) t[i*2+2] = s[i], t[2*i+3] = '#';
t[len*2+2] = '\0';
int id = 0, mx = 0;
//id为一直右边界最大的回文串的中心, mx=id+p[id]
memset(p, 0, sizeof(int)*len*2+3);
for(int i=1; i<len*2+2; ++i)
{
//mx<=i则要从一个字符开始向两边匹配
//否则取p[id*2-i](i关于id的对称点), mx-i(i与id为中心的回文串最右边的距离)的最小值
p[i] = mx > i ? min(p[id*2-i], mx-i) : 1;
while(t[i+p[i]] == t[i-p[i]]) ++p[i];//继续匹配
if(i+p[i] > mx) mx = i+p[i], id = i;//更新mx和id
}
}

int main()
{
while(cin >> s)
{
manacher();
cout << t << endl;
for(int i=0; i<(int)strlen(t); ++i) cout << p[i];
cout << endl;
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: