[POI2005]SZA-Template

KMP+双向链表
由题意易知解必须满足的条件是解既是前缀也是后缀,然后就把所有的解打上标记,建出一棵fail树,然后发现如果这个串能作为解的话就是它的相邻两个之间的距离差不能超过其长度。
然后就可以用双向链表维护这个,记录一个mx表示最大差值即可。

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N=5e5+5;
char s[N];
struct List{
    int nxt,to;
}e[N];
int len,nxt[N],ecnt,head[N],ans,mx,pre[N],Nxt[N];
bool usef[N];
void add(int bg,int ed) {e[++ecnt]=(List){head[bg],ed},head[bg]=ecnt;}
void del(int x) {
    Nxt[pre[x]]=Nxt[x];
    pre[Nxt[x]]=pre[x];
    mx=max(mx,Nxt[x]-pre[x]);
    for(int i=head[x];i;i=e[i].nxt) del(e[i].to);
}
void dfs(int x) {
    if(mx<=x) return ans=x,void();
    int t=0;
    for(int i=head[x];i;i=e[i].nxt) {
        if(!usef[e[i].to]) del(e[i].to);else t=e[i].to;
    }
    if(t) dfs(t);
}
int main() {
    scanf("%s",s+1);
    len=strlen(s+1);
    add(0,1);
    for(int i=2,j=0;i<=len;i++) {
        while(j&&s[j+1]!=s[i]) j=nxt[j];
        if(s[j+1]==s[i]) j++;
        nxt[i]=j;
        add(j,i);
    }
    for(int i=len;i;i=nxt[i]) 
        usef[i]=1;
    for(int i=1;i<=len;i++) pre[i]=i-1,Nxt[i]=i+1;
    Nxt[len]=0;
    mx=1;
    dfs(0);
    cout<<ans<<endl;
    return 0;
}


posted @ 2018-10-18 15:58  SWHsz  阅读(308)  评论(0编辑  收藏  举报