#计算回文字符串最大长度模板题

计算回文字符串最大长度模板题

如果一个字符串正着读和倒着读是一样的,则称它是回文的。

给定一个长度为N的字符串S,求他的最长回文子串的长度是多少。

输入格式
输入将包含最多30个测试用例,每个测试用例占一行,以最多1000000个小写字符的形式给出。

输入以一个以字符串“END”(不包括引号)开头的行表示输入终止。

输出格式
对于输入中的每个测试用例,输出测试用例编号和最大回文子串的长度(参考样例格式)。

每个输出占一行。

输入样例:
abcbabcbabcba
abacacbaaaab
END
输出样例:
Case 1: 13
Case 2: 6

 	#include<iostream>
	#include<algorithm>
	#include<stdio.h>
	#include<cstring>
	using namespace std;
	const int N = 10000010;
	const int bace = 131;
	unsigned long long hl[N], hr[N], p[N];
	char s[N];
	unsigned long long get(unsigned long long h[], int l, int r)
	{
		return h[r] - h[l - 1] * p[r - l + 1];
	}
	int main()
	{
		p[0] = 1;
		int T = 1;
		while (cin>>s+1, strcmp(s + 1, "END"))
		{
			int n = strlen(s + 1);
			for (int i = n * 2; i > 0; i -= 2)//在每个字符中检查入一个数大于'z',这样好计算,就都变成了奇数个字符
			{
				s[i] = s[i / 2];
				s[i - 1] = 'z' + 1;
			}
			n *= 2;
			for (int i = 1, j = n; i <= n; i++, j--)//求出字符串循序和逆序的哈希值
			{
				hl[i] = hl[i - 1] * bace + (s[i] - 'a' + 1);
				hr[i] = hr[i - 1] * bace + (s[j] - 'a' + 1);
				p[i] = p[i - 1] * bace;
			}
			int ans = 0;
			for (int i = 1; i <= n; i++)//枚举1~n的字符,找到一个个数mid,使得以这个字符为中心,半径为mid的一串字符串是最长的回文字符串 形如i-mid~i~i+mid,
			{
				int l = 0, r = min(i - 1, n - i);
				while (l < r)//找到mid
				{
					int mid = l + r + 1 >> 1;
					if (get(hl, i - mid, i - 1) != get(hr, n - (i + mid) + 1, n - (i + 1) + 1))//计算i左边到i-mid的字符串哈希值,是不是等于i字符右边到i+mid的哈希值,为啥是n-(i+mid)+1,n-(i+1)+1呢,因为hr数组计算的就是反过来以后的哈希值,1对应的是n,x对应的就是n-x+1,
						r = mid - 1;
					else
						l = mid;
				}
				if (s[i - l] <= 'z')如果i-mid的这个数是字母,就把mid+1,你可能会问不用乘以二么,其实上面就已经是乘上2
                 得了
					ans = max(ans, l + 1);
				else//如果不是字母,就正常输出
					ans = max(ans, l);
			}
			printf("Case %d: %d\n", T++, ans);
		}
		return 0;
	
	}
posted @ 2020-02-07 11:20  arbor_one  阅读(225)  评论(0)    收藏  举报