BZOJ2565: 最长双回文串
? 解题记录 ? ? BZOJ ? ? Manacher ?    2017-11-17 21:56:37    546    0    0

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新加数据一组

 

Manacher练手题,主要思想是开一个len数组表示当前下标结尾最长的回文子串长度,这样就可以在Manacher的过程中一边匹配一边类似dp的统计答案了。代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 2e5 + 5;
int len[maxn << 1], RL[maxn << 1], mx, cnt;
char words[maxn], s[maxn << 1];

void Manacher() {
	int Mr = 0, Mpos = 0, l, r;
	for(register int i = 0; i < cnt; ++i) {
		RL[i] = min(RL[(Mpos << 1) - i]/*对称位置*/, Mr - i/*长度超过目前范围*/);
		for(;(l = i - RL[i]) >= 0 && (r = i + RL[i]) < cnt && s[l] == s[r]; ++RL[i]) {
			if(l > 0) mx = max(mx, len[l - 1] + RL[i] * 2 + 1);
			len[i + RL[i]] = max(len[i + RL[i]], RL[i] * 2 + 1);		
		}
		--RL[i];
		if(Mr < i + RL[i]) Mpos = i, Mr = i + RL[i];
	}
}

int main() {
	scanf("%s", words);
	int sl = strlen(words);
	for(register int i = 0; i < sl; ++i)
		s[cnt++] = '#', s[cnt++] = words[i];
	s[cnt++] = '#';
	Manacher();
	printf("%d", (mx + 1) / 2);
	return 0;
}
 

 

上一篇: 洛谷P3796 【模板】AC自动机(加强版)

下一篇: 省选内容:回顾与前进

546 人读过
立即登录, 发表评论.
没有帐号? 立即注册
0 条评论
文档导航