【BZOJ2803】【Poi2012】Prefixuffix hash+推性質

鏈接:

#include <stdio.h>
int main()
{
    puts("轉載請註明出處[vmurder]謝謝");
    puts("網址:blog.csdn.net/vmurder/article/details/45768837");
}

題解:

首先我們如果設原串爲串[ 1,n ]
然後 fi 表示串[ i+1,ni ]中最長的串長使得串[ i+1,i+fi ]==串[nifi+1,ni ]
這時存在一個性質 fi1<=fi+2
然後就可以線性遞推啦!

證明:

現在讓我們來反證一下這個性質:
下圖有四種情況,f[i]爲紅色, f[i-1]爲全圖。
bzoj2803性質證明
顯然無論何時,f[i-1]對應圖去掉兩側點,皆可以保證是一個f[i]。
所以fi1<=fi+2

代碼:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1001000
#define mod 1000000009
#define base 1000000007
using namespace std;
int n,ans;
char s[N];
long long sum[N],hash[N],pw[N];
long long gethash(int l,int r)
{return (hash[r]+mod-hash[l-1]*pw[r-l+1]%mod)%mod;}
int main()
{
    freopen("test.in","r",stdin);

    int i,j,k;

    scanf("%d",&n);
    for(pw[0]=i=1;i<=n;i++)pw[i]=(long long)pw[i-1]*base%mod;
    scanf("%s",s+1);
    for(i=1;i<=n;i++)
    {
        hash[i]=(hash[i-1]*base%mod+s[i])%mod;
        sum[i]=sum[i-1]+s[i];
    }
    for(i=n>>1,j=0;~i;i--)
        if(sum[i]==sum[n]-sum[n-i])
            if(gethash(1,i)==gethash(n-i+1,n))
                for(j=min(n/2-i,j+2);j>=0;j--)
                    if(sum[i+j]-sum[i]==sum[n-i]-sum[n-i-j])
                        if(gethash(i+1,i+j)==gethash(n-i-j+1,n-i))
                            {ans=max(ans,i+j);break;}
    printf("%d\n",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章