最长回文
Time Limit:2000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
Description
给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.
回文就是正反读都是一样的字符串,如aba, abba等
回文就是正反读都是一样的字符串,如aba, abba等
Input
输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c...y,z组成的字符串S
两组case之间由空行隔开(该空行不用处理)
字符串长度len <= 110000
两组case之间由空行隔开(该空行不用处理)
字符串长度len <= 110000
Output
每一行一个整数x,对应一组case,表示该组case的字符串中所包含的最长回文长度.
Sample Input
aaaa abab
Sample Output
4 3
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define N 110005
char str[N];
char strf[2 * N];
int rad[2 * N];
int len;
void init(){
int i, j;
len = strlen(str);
strf[0] = '@';
strf[1] = '#';
for(i = 0; i < len; i ++){
strf[i * 2 + 2] = str[i];
strf[i * 2 + 3] = '#';
}
strf[len * 2 + 2] = '$';
len = len * 2 + 3;
}
int main(){
while(~scanf("%s", str)){
init();
//cout << strf << endl;
memset(rad, 0, sizeof(rad));
int mx = 0, id;
int len = strlen(strf);
for(int i = 1; i < len - 1; i++){
if(mx > i)
rad[i] = min(rad[2 * id - i], rad[id] + id - i);
else
rad[i] = 1;
while(strf[i + rad[i]] == strf[i - rad[i]])
rad[i]++;
if(rad[i] + i > mx){
mx = rad[i] + i;
id = i;
}
}
int ans = 0;
for(int i = 0; i < len; i ++){
//printf("%d\n", rad[i]);
if(rad[i] > ans)
ans = rad[i];
}
printf("%d\n", ans - 1);
}
return 0;
}
manacher部分还可以写成如下形式,个人认为更容易理解(参考点击打开链接),不过注意到最后ans不用再减一
for(int i = 1, j = 0, k; i < len;){
while(strf[i - j - 1] == strf[i + j + 1])
j ++;
rad[i] = j;
for(k = 1; k <= j && rad[i - k] != rad[i] - k; k ++){
rad[i + k] = min(rad[i - k], rad[i] - k);
}
i += k;
j = max(j - k, 0);
}