HDU 3068 - 最长回文串(manacher算法)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=3068
最长回文
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 25520 Accepted Submission(s): 9422
Problem 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
manacher算法的模板题目,可以在O(n)时间内计算出最长的回文串,算法讲解如下
https://www.felix021.com/blog/read.php?2040
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 110050;
char s1[maxn], s2[maxn * 2];
int p[maxn * 2], ans;
//把'abab\0'这种普通的字符串变成'$a#b#a#b#\0'便于计算
void init() {
ans = 0;
s2[0] = '$';
s2[1] = '#';
int i, j;
for (i = 0, j = 2; s1[i]; ++i, ++j) {
s2[j] = s1[i];
s2[++j] = '#';
}
s2[j] = '\0';
}
void manacher() {
memset(p, 0, sizeof(p));
int id = 0, mx = 1;//初始化条件
for (int i = 1; s2[i]; ++i) {//p[0]不需要处理
p[i] = mx > i ? min(p[2 * id - i], mx - i) : 1;
while (s2[i - p[i]] == s2[i + p[i]]) ++p[i];
if (i + p[i] > mx) {
mx = i + p[i];
id = i;
}
ans = max(ans, p[i] - 1);
}
}
int main() {
while (scanf("%s", s1) == 1) {
init();
manacher();
printf("%d\n", ans);
}
return 0;
}