bzoj 2946/Spoj 8222 后缀自动机

11 篇文章 1 订阅
4 篇文章 0 订阅

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2946

后缀自动机模板,详见clj课件

code
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 4010
using namespace std;
int n;
char str[N];

struct node
{
    int cnt,last,p,q,np,nq;
    int len[N],fa[N],son[N][26];
    int hash[N];
    int a[N],sa[N],cl[N];
    node()
    {
        cnt=last=1;
    }
    void Insert(int c)
    {
        p=last,last=np=++cnt,len[np]=len[p]+1;
        while(p&&!son[p][c])son[p][c]=np,p=fa[p];
        if(!p)fa[np]=1;
        else{
            int q=son[p][c];
            if(len[q]==len[p]+1)fa[np]=q;
            else{
                nq=++cnt,len[nq]=len[p]+1;
                fa[nq]=fa[q];
                memcpy(son[nq],son[q],sizeof(son[q]));
                fa[q]=fa[np]=nq;
                while(son[p][c]==q)son[p][c]=nq,p=fa[p];
            }
        }
    }
    void build()
    {
        scanf("%s",str+1);
        int len=strlen(str+1);
        for(int i=1;i<=len;i++)Insert(str[i]-'a');
    }
    void pre()
    {
        memset(str,0,sizeof(str));
        memset(cl,0,sizeof(cl));
        scanf("%s",str+1);
        int tmp=0;
        p=1;
        for(int i=1;i<=strlen(str+1);i++)
        {
            int c=str[i]-'a';
            if(son[p][c])p=son[p][c],tmp++;
            else{
                while(p&&!son[p][c])p=fa[p];
                if(!p)p=1,tmp=0;
                else tmp=len[p]+1,p=son[p][c];
            }
            cl[p]=max(cl[p],tmp);
        }
        for(int i=cnt;i>0;i--)
        {
            int t=sa[i];
            a[t]=min(a[t],cl[t]);
            if(cl[t]&&fa[t])cl[fa[t]]=len[fa[t]];
        }
    }
    void work()
    {
        for(int i=1;i<=cnt;i++)hash[len[i]]++,a[i]=len[i];
        for(int i=1;i<=cnt;i++)hash[i]+=hash[i-1];
        for(int i=1;i<=cnt;i++)sa[hash[len[i]]--]=i;
        for(int i=2;i<=n;i++)pre();
    }
}sam;

int main()
{
    cin>>n;
    sam.build();
    sam.work();
    int ans=0;
    for(int i=1;i<=sam.cnt;i++)ans=max(ans,sam.a[i]);
    cout<<ans<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值