SCU3075 回文子串
? 解题记录 ? ? Manacher ? ? 杂OJ ?    2017-09-16 14:05:32    380    0    0

Description

全部由小写字母构成且长度不超过 100000 的非空字符串,求最长的连续子字符串
使得该字符串与其反转字符串相等

Input

输入包含多组测试数据,每组数据一行,为一个长度不超过 100000 的非空字符串

Output

每组数据输出一行,为最长的连续子字符串的长度

Sample Input

abcbad
abccba
abcba
abbacc
ccabba

Sample Output

5
6
5
4
4

根据今天连WA带TLE的经验可以归纳出在写Manacher的时候需要注意这几点:

    1、不同case之间要清零清干净

    2、位运算的优先级低于加减乘除…………

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

void Manacher() {
	int Mr = 0, Mpos = 0;
	int len = cnt;
	for(register int i = 0; i < len; ++i) {
		if(i <= Mr) {
			RL[i] = min(RL[(Mpos << 1) - i], Mr - i); //记得位运算
			for(; i - RL[i] >= 0 && i + RL[i] <= len && s[i - RL[i]] == s[i + RL[i]]; ++RL[i]);
			--RL[i];
			if(Mr < RL[i] + i) Mr = i + RL[i], Mpos = i;
		}else {
			for(; i - RL[i] >= 0 && i + RL[i] <= len && s[i - RL[i]] == s[i + RL[i]]; ++RL[i]);
			--RL[i];
			Mr = i + RL[i], Mpos = i;
		}
		mx = max(mx, RL[i]);
	}
}

int main() {
	while(scanf("%s", r) != -1) {
		cnt = mx = 0;
		int mxr = strlen(r);
		for(register int i = 0; i < mxr; ++i)
			{s[cnt++] = '#', s[cnt++] = r[i];}
		s[cnt++] = '#';
		Manacher();
		printf("%d\n", mx);
		memset(RL, 0, sizeof(RL));
	}
	return 0;
}

 

 

上一篇: 51Nod1089 最长回文子串 V2

下一篇: UVa11552 Fewest Flops

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