zoukankan      html  css  js  c++  java
  • P4287 [SHOI2011]双倍回文

    求最长双倍回文子串。
    考虑建PAM,我们可以知道最长回文子串,但是如何知道最长双倍回文子串呢?
    我们发现如果这个子串是双倍回文子串,那么该子串<=len/2的最长回文子串一定是=len/2的,我们可以再记录一个fail'表示<=len/2的最长回文子串后缀。
    求答案的时候枚举每个位置判断fail'的len即可。
    对于fail'的求法,类似fail的求法再判断len的限制即可。
    还有一种方法,就是建完PAM以后在遍历一遍回文树,并用个桶实时存储当前每个长度的个数。每次看看有没有即可。

    或者可以用manacher来实现。

    #include<cstdio>
    #define N 500010
    #define db double
    #define ll long long
    #define fo(x,a,b) for (int x=(a);x<=(b);x++)
    #define fd(x,a,b) for (int x=(a);x>=(b);x--)
    using namespace std;
    int n,ans=0;
    char s[N];
    
    struct PAM {
    	int t[N<<1][26],len[N<<1],fail[N<<1],trans[N<<1],tot=1,las;
    	
    	void init() {
    		len[0]=0,fail[0]=trans[0]=1;
    		len[1]=-1,fail[1]=0,tot=1,las=1;
    	}
    	
    	int get_fail(int pos,int x) {
    		while (s[pos-len[x]-1]!=s[pos])
    			x=fail[x];
    		return x;
    	}
    	
    	int get_fail(int pos,int x,int son,int lim) {
    		while (s[pos-len[x]-1]!=s[pos]||len[t[x][son]]>lim)
    			x=fail[x];
    		return x;
    	}
    	
    	void ins(int x) {
    		int now=get_fail(x,las);
    		if (! t[now][s[x]-'a']) {
    			len[++tot]=len[now]+2;
    			int temp=get_fail(x,fail[now]);
    			fail[tot]=t[temp][s[x]-'a'];
    			if (len[tot]<=2) trans[tot]=fail[tot];
    			else {
    				temp=get_fail(x,trans[now],s[x]-'a',len[tot]/2);
    				trans[tot]=t[temp][s[x]-'a'];
    			}
    			t[now][s[x]-'a']=tot;
    		}
    		las=t[now][s[x]-'a'];
    	}
    	
    	int query() {
    		int res=0;
    		fo(i,2,tot) {
    			if (len[i]%4==0&&len[trans[i]]*2==len[i]) {
    				if (len[i]>res) res=len[i];
    			}
    		}
    		return res;
    	}
    }tr;
    
    int main() {
    	freopen("string.in","r",stdin);
    	freopen("string.out","w",stdout);
    	scanf("%d%s",&n,s+1);
    	tr.init();
    	fo(i,1,n) tr.ins(i);
    	ans=tr.query();
    	printf("%d
    ",ans);
    	return 0;
    }
    
    
    转载需注明出处。
  • 相关阅读:
    FZU 2150 Fire Game
    POJ 3414 Pots
    POJ 3087 Shuffle'm Up
    POJ 3126 Prime Path
    POJ 1426 Find The Multiple
    POJ 3278 Catch That Cow
    字符数组
    HDU 1238 Substing
    欧几里德和扩展欧几里德详解 以及例题CodeForces 7C
    Codeforces 591B Rebranding
  • 原文地址:https://www.cnblogs.com/jz929/p/14819577.html
Copyright © 2011-2022 走看看