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等
 

Input
输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c...y,z组成的字符串S
两组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;
}


posted @ 2018-01-28 10:54  不想吃WA的咸鱼  阅读(86)  评论(0编辑  收藏  举报