【bzoj2565】最长双回文串

2565: 最长双回文串

Time Limit: 10 Sec   Memory Limit: 128 MB
Submit: 2579   Solved: 1316
[ Submit][ Status][ Discuss]

Description

顺序和逆序读起来完全一样的串叫做回文串。比如 acbca 是回文串,而 abc 不是( abc 的顺序为 “abc” ,逆序为 “cba” ,不相同)。
输入长度为 n 的串 S ,求 S 的最长双回文子串 T, 即可将 T 分为两部分 X Y ,( |X|,|Y|≥1 )且 X Y 都是回文串。

Input

一行由小写英文字母组成的字符串S

Output

一行一个整数,表示最长双回文子串的长度。

Sample Input

baacaabbacabb

Sample Output

12

HINT

样例说明

从第二个字符开始的字符串aacaabbacabb可分为aacaa与bbacabb两部分,且两者都是回文串。

对于100%的数据,2≤|S|≤10^5


2015.4.25新加数据一组

Source

2012国家集训队Round 1 day2

[ Submit][ Status][ Discuss]





。。。怎么评价这个非常傻X的题目呢

这题其实就是一个manacher,记f[i]为以i结尾的最长回文串,跑一遍manacher,然后直接找就好啦

但是蒟蒻一开始不会manacher。。。。

于是蒟蒻YY了一个做法

先把字符串正着反着hash一下,然后枚举每个字符,二分它能向左/向右延伸的最大长度,记录下它的最长左端点和右端点

显然对于一个回文串的左端点,要使双回文串最长,肯定是要找到一个能够包含它的、中心对称点最远的回文串

那么要怎么找呢。。。。。

蒟蒻非常的傻X。。连ST都懒得打直接上了线段树。。。(事实上用ST会更快233)

manacher大概在bzoj上跑了60ms,线段树3S。。。。。。。。。

真菜啊。。。。

代码(manacher):
#include
#include
#include
#include
#include
#include
#include
using namespace std;

typedef long long LL;

const int maxn = 200100;

char s[maxn],a[maxn];
int n,p[maxn],f[maxn];

inline LL getint()
{
	LL ret = 0,f = 1;
	char c = getchar();
	while (c < '0' || c > '9')
	{
		if (c == '-') f = -1;
		c = getchar();
	}
	while (c >= '0' && c <= '9')
		ret = ret * 10 + c - '0',c = getchar();
	return ret * f;
}

int main()
{
	scanf("%s",a + 1); n = strlen(a + 1);
	n = 2 * n + 1;
	for (int i = 1; i <= n; i++)
	{
		if (i & 1) s[i] = '#';
		else s[i] = a[i / 2]; 
	}
	s[0] = '$';
	int mx = 0,pos = 0;
	for (int i = 1; i <= n; i++)
	{
		if (i <= mx) p[i] = min(mx - i + 1,p[2 * pos - i]);
		else p[i] = 1;
		while (s[i + p[i]] == s[i - p[i]]) 
		{
			f[i + p[i]] = max(f[i + p[i]],p[i] + 1);
			p[i]++;
		}
		if (p[i] + i - 1 > mx) mx = i + p[i] - 1 , pos = i;
	}
	int ans = 0;
	for (int i = 1; i <= n; i++) ans = max(ans,p[i] + f[i - p[i]] - 1);
	printf("%d",ans);
	return 0;
}


你可能感兴趣的:(线段树,manacher,哈希)