最长回文
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 30492 Accepted Submission(s): 11173
Problem Description
给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.
回文就是正反读都是一样的字符串,如aba, abba等
Input
输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c...y,z组成的字符串S
两组case之间由空行隔开(该空行不用处理)
字符串长度len <= 110000
Output
每一行一个整数x,对应一组case,表示该组case的字符串中所包含的最长回文长度.
Sample Input
aaaa
abab
Sample Output
4
3
Source
2009 Multi-University Training Contest 16 - Host by NIT
#include <bits/stdc++.h>
using namespace std;
const int mn = 110010;
int ans;
char ch[mn];
char temp[2 * mn];
int tp[2 * mn];
int init(char ch[])
{
int len = strlen(ch);
temp[0] = '@';
for (int i = 1; i <= 2 * len; i += 2)
{
temp[i] = '#';
temp[i + 1] = ch[i / 2];
}
temp[2 * len + 1] = '#';
temp[2 * len + 2] = '$';
temp[2 * len + 3] = '\0';
return 2 * len + 1; // 转换后字符串的长度
}
void manacher(char ch[])
{
int tlen = init(ch);
int mx = 0, id = 0;
for (int i = 1; i <= tlen; i++) // 操作转换后字符串
{
if (mx >= i)
tp[i] = min(tp[2 * id - i], mx - i + 1);
else
tp[i] = 1;
while (temp[i - tp[i]] == temp[i + tp[i]])
tp[i]++;
if (mx < i + tp[i] - 1)
{
mx = i + tp[i] - 1;
id = i;
}
ans = max(ans, tp[i] - 1); /// 原串中回文串长度 = tp[i] - 1
}
}
int main()
{
while (~scanf("%s", ch))
{
ans = 0;
manacher(ch);
printf("%d\n", ans);
}
}