-paozi-

导航

最长回文子串--马拉车(?)

每个回文串一定有一个中心,然而如果这个串长度是偶数,它的中心是空的,所以我们把长度为len的字符串变成长度2*len+1的字符串,每两个字符中间补上一个相同的字符。

用r[i]表示以i为中心的最长回文半径(如果字符两边不存在相同字符,r[i]=1)。记录下该半径对应的中心pos和半径达到的最远距离maxx,每当我们遍历一个i的时候,可以找到它对于pos对称的位置j,它的回文串半径一定大于等于j的回文串半径。如果j的回文串半径<2*pos-i+1,r[i]=r[j],反之,在maxx之外的距离可能也是i为中心的回文串的范围,所以我们一个个判断,更新maxx

因为maxx在每个位置最多被更新一次,所以复杂度O(n),看起来。。。很神奇?

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<iostream>
using namespace std;

char ss[1005];
char s[2010];
int r[2005];//最长回文半径

int main()
{
	gets(ss+1);
	int len=strlen(ss+1);
	for(int i=1;i<=len;i++){
		s[i*2]=ss[i];
		s[i*2-1]='#';
	}
	s[len*2+1]='#';
	int pos=0,maxx=0;
	for(int i=1;i<=len*2+1;i++){
		if(pos){
			r[i]=min(maxx-i+1,r[pos*2-i]);
			while(i+r[i]<=len*2+1&&i-r[i]>0&&s[i+r[i]]==s[i-r[i]]) r[i]++;
			if(i+r[i]-1>maxx){
				maxx=i+r[i]-1;
				pos=i;
			}
		}
	}
	return 0;
}

  

posted on 2017-10-27 17:54  -paozi-  阅读(238)  评论(0编辑  收藏  举报