Manacher算法:求解最长回文字符串,时间复杂度为O(N)
这一个题目因为对于所有的数据,满足1<=Q<=30,字符串长度<=10^6。
字符串的长度很长,不能使用我们平时使用的类似于dp的开两维数组的解法,所以我们只有一种专门来求解这一类问题的解法,Manacher算法:求解最长回文字符串,时间复杂度为O(N)。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAX = 1000005;
int len, p[2 * MAX];
char str[2 * MAX], newstr[2 * MAX];
void change()
{
int i;
newstr[0] = '@';
newstr[1] = '#';
for (i = 0; i < len; i++)
{
newstr[2 * i + 2] = str[i];
newstr[2 * i + 3] = '#';
}
newstr[2 * len + 2] = '\0';
}
void Manacher()
{
int i, j, id, maxid = 0, ans = 1;
len = 2 * len + 2;
for (i = 0; i < len; i++){
if (maxid > i){
p[i] = min(p[2 * id - i], maxid - i);
}
else{
p[i] = 1;
}
while (newstr[i + p[i]] == newstr[i - p[i]])
p[i]++;
if (p[i] + i > maxid){
maxid = p[i] + i;
id = i;
}
if (ans < p[i])
ans = p[i];
}
for (i = id, j = 0; i < id + ans; i++)
{
if (newstr[i] != '#')
{
str[j] = newstr[i];
j++;
}
}
str[id + ans] = '\0';
cout << ans - 1 << endl;
}
int main()
{
int t;
cin >> t;
while (t--)
{
cin >> str;
len = strlen(str);
change();
Manacher();
}
return 0;
}
/**************************************************************
Problem: 1681
User: liuyaning
Language: C++
Result: Accepted
Time:128 ms
Memory:12988 kb
****************************************************************/