【后缀自动机例题】

学习笔记戳这里: 折跃

论文戳这里: 折跃

论文中的例题

SPOJ NSUBSTR - Substrings

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
#define MAXN 2500010
int N,a[MAXN],dp[MAXN],st[MAXN],Right[MAXN<<1],id[MAXN<<1];
char s[MAXN];
namespace SAM
{
    int son[MAXN<<1][27],len[MAXN<<1],par[MAXN<<1];
    int sz,last,root;
    inline void Init() {root=sz=last=1;}
    inline void Extend(int c)
    {
        int cur=++sz,p=last;
        len[cur]=len[p]+1;
        while (p && !son[p][c]) son[p][c]=cur,p=par[p];
        if (!p)    par[cur]=root;
        else 
            {
                int q=son[p][c];
                if (len[p]+1==len[q]) par[cur]=q;
                else 
                    {
                        int nq=++sz;
                        memcpy(son[nq],son[q],sizeof(son[nq])); 
                        par[nq]=par[q]; len[nq]=len[p]+1;
                        while (p && son[p][c]==q)
                            son[p][c]=nq,p=par[p];
                        par[cur]=par[q]=nq;
                    }
            }
        last=cur;
    }
    inline void Build() {Init(); for (int i=1; i<=N; i++) Extend(a[i]=s[i]-'a'+1);}
}using namespace SAM;
int main()
{
    scanf("%s",s+1); N=strlen(s+1);
    SAM::Build();
    for (int i=1,now=root; i<=N; i++) now=son[now][a[i]],Right[now]++;
    for (int i=1; i<=sz; i++) st[len[i]]++;
    for (int i=1; i<=N; i++) st[i]+=st[i-1];
    for (int i=1; i<=sz; i++) id[st[len[i]]--]=i;
    for (int i=sz; i>=1; i--) Right[par[id[i]]]+=Right[id[i]];
    for (int i=1; i<=sz; i++) dp[len[i]]=max(dp[len[i]],Right[i]);
    for (int i=N; i>=1; i--) dp[i-1]=max(dp[i-1],dp[i]);
    for (int i=1; i<=N; i++) printf("%d
",dp[i]);
    return 0;
} 
View Code

SPOJ SUBLEX - Lexicographical Substring Search

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define MAXN 900010
char A[MAXN],ans[MAXN];
int N,Q,K;
namespace SAM
{
    int son[MAXN<<1][27],par[MAXN<<1],len[MAXN<<1],root,last,sz;
    inline void Init() {root=sz=last=1;}
    inline void Extend(int c)
    {
        int cur=++sz,p=last;
        len[cur]=len[p]+1;
        while (p && !son[p][c]) son[p][c]=cur,p=par[p];
        if (!p) par[cur]=root;
        else
            {
                int q=son[p][c];
                if (len[p]+1==len[q]) par[cur]=q;
                else
                    {
                        int nq=++sz;
                        memcpy(son[nq],son[q],sizeof(son[nq]));
 
                        len[nq]=len[p]+1;
                        par[nq]=par[q];
                        while (p && son[p][c]==q) son[p][c]=nq,p=par[p];
                        par[cur]=par[q]=nq;
                    }
            }
        last=cur;
    }
    inline void Build() {Init(); for (int i=1; i<=N; i++) Extend(A[i]-'a'+1);}
    int st[MAXN],id[MAXN<<1],sum[MAXN<<1];
    inline void Pre()
    {
          for (int i=1; i<=sz; i++) st[len[i]]++;
        for (int i=1; i<=N; i++) st[i]+=st[i-1];
        for (int i=1; i<=sz; i++) id[st[len[i]]--]=i;
        for (int i=sz,Sum=0; i>=1; i--,Sum=0)
            {
                for (int j=1; j<=26; j++)
                    Sum+=sum[son[id[i]][j]];
                sum[id[i]]=Sum+1;
            }
    }
    inline void Query(int K)
    {
        int now=root,tot=0;
        while (K)
            {
                for (int i=1; i<=26; i++)
                    if (son[now][i])
                        if (sum[son[now][i]]>=K)
                            {
                                ans[++tot]='a'+i-1,K--,now=son[now][i];
                                break;
                            }
                        else K-=sum[son[now][i]];
 
            }
        ans[++tot]=0;
    }
}using namespace SAM;
int main()
{
    scanf("%s",A+1);
    N=strlen(A+1);
    SAM::Build();
    SAM::Pre();
    scanf("%d",&Q);
    while (Q--) scanf("%d",&K),Query(K),puts(ans+1);
    return 0;
} 
View Code

SPOJ LCS - Longest Common Substring

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define MAXN 250010
char A[MAXN],B[MAXN];
int N,M;
namespace SAM
{
    int son[MAXN<<1][27],par[MAXN<<1],len[MAXN<<1],root,last,sz;
    inline void Init() {root=sz=last=1;}
    inline void Extend(int c)
    {
        int cur=++sz,p=last;
        len[cur]=len[p]+1;
        while (p && !son[p][c]) son[p][c]=cur,p=par[p];
        if (!p) par[cur]=root;
        else
            {
                int q=son[p][c];
                if (len[p]+1==len[q]) par[cur]=q;
                else
                    {
                        int nq=++sz;
                        memcpy(son[nq],son[q],sizeof(son[nq]));
                        len[nq]=len[p]+1;
                        par[nq]=par[q];
                        while (p && son[p][c]==q) son[p][c]=nq,p=par[p];
                        par[cur]=par[q]=nq;
                    }
            }
        last=cur;
    }
    inline void Build() {Init(); for (int i=1; i<=N; i++) Extend(A[i]-'a'+1);}
    inline int Query()
     {
         int now=root,Len=0,ans=0;
        for (int i=1; i<=M; i++)
            {
                int c=B[i]-'a'+1;
                if (son[now][c]) now=son[now][c],Len++;
                else
                    {
                        while (now && !son[now][c]) now=par[now];
                        if (!now) now=root,Len=0;
                            else Len=len[now]+1,now=son[now][c];
                    }
                ans=max(ans,Len);
            }
        return ans;
     }
}using namespace SAM;
int main()
{
    scanf("%s%s",A+1,B+1);
    N=strlen(A+1),M=strlen(B+1);
    SAM::Build();
    printf("%d
",SAM::Query());
    return 0;
} 
View Code

SPOJ LCS2 - Longest Common Substring II

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define MAXN 250010
char A[MAXN],B[MAXN];
int N,M;
namespace SAM
{
    int son[MAXN<<1][27],len[MAXN<<1],par[MAXN<<1],mat[MAXN<<1],minn[MAXN<<1];
    int sz,root,last;
    inline void Init() {last=root=sz=1;}
    inline void Extend(int c)
    {
        int cur=++sz,p=last;
        len[cur]=len[p]+1;
        while (p && !son[p][c]) son[p][c]=cur,p=par[p];
        if (!p) par[cur]=root;
        else
            {
                int q=son[p][c];
                if (len[p]+1==len[q]) par[cur]=q;
                else
                    {
                        int nq=++sz;
                        memcpy(son[nq],son[q],sizeof(son[nq]));
                        len[nq]=len[p]+1,par[nq]=par[q];
                        while (p && son[p][c]==q) son[p][c]=nq,p=par[p];
                        par[cur]=par[q]=nq;
                    }
            }
        last=cur;
    }
    inline void Build() {Init(); for (int i=1; i<=N; i++) Extend(A[i]-'a'+1);}
    int st[MAXN],id[MAXN<<1];
    inline void Pre()
    {
        for (int i=1; i<=sz; i++) st[len[i]]++;
        for (int i=1; i<=N; i++) st[i]+=st[i-1];
        for (int i=1; i<=sz; i++) id[st[len[i]]--]=i;
        for (int i=1; i<=sz; i++) minn[i]=len[i];
    }
    inline void Match()
    {
        for (int i=1; i<=sz; i++) mat[i]=0;
        int now=root,Len=0;
        for (int i=1; i<=M; i++)
            {
                int c=B[i]-'a'+1;
                if (son[now][c])
                    now=son[now][c],Len++;
                else
                    {
                        while (now && !son[now][c]) now=par[now];
                        if (!now) now=root,Len=0;
                            else Len=len[now]+1,now=son[now][c];
                    }
                mat[now]=max(mat[now],Len);
            }
    }
    inline void Query()
    {
         for (int i=sz; i>=1; i--)
            {
                int now=id[i];
                minn[now]=min(minn[now],mat[now]);
                if (par[now] && mat[now]) mat[par[now]]=len[par[now]];
            }
    }
}
int ans=0;
int main()
{
    scanf("%s",A+1); N=strlen(A+1);
    SAM::Build();
    SAM::Pre();
    while (~scanf("%s",B+1)) M=strlen(B+1),SAM::Match(),SAM::Query();
    for (int i=1; i<=SAM::sz; i++) ans=max(ans,SAM::minn[i]);
    printf("%d
",ans);
    return 0;
} 
View Code

BZOJ SubString

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define MAXN 1200010
char S[MAXN];
int N,Q,M,ans,Mask;
inline void read()
{
    string str=S+1;
    int mask=Mask;
    for (int i=0; i<str.length(); i++)
        {
            mask=(mask*131+i)%str.length();
            swap(str[i],str[mask]);
        }
    for (int i=0,tot=0; i<str.length(); i++) S[++tot]=str[i];
}
namespace LCT
{
    int fa[MAXN],ch[MAXN][2],val[MAXN],tag[MAXN];
    inline bool is_root(int x) {return !fa[x] || ch[fa[x]][1]!=x&&ch[fa[x]][0]!=x;}
    inline void Add(int x,int v) {if (!x) return; val[x]+=v,tag[x]+=v;}
    inline void Pushdown(int x) {if (tag[x]) Add(ch[x][0],tag[x]),Add(ch[x][1],tag[x]),tag[x]=0;}
    inline void Rotate(int x)
    {
        int y=fa[x],w=ch[y][1]==x,z=fa[y];
        ch[y][w]=ch[x][w^1];
        if (ch[x][w^1]) fa[ch[x][w^1]]=y;
        if (ch[z][0]==y) ch[z][0]=x; else if (ch[z][1]==y) ch[z][1]=x;
        fa[x]=fa[y]; fa[y]=x; ch[x][w^1]=y;
    }
    int stack[MAXN];
    inline void Splay(int x)
    {
        int top=0,t=x,y; stack[++top]=x;
        while (!is_root(t)) stack[++top]=t=fa[t];
        while (top) Pushdown(stack[top--]);
        while (!is_root(x))
            {
                y=fa[x];
                if (!is_root(y))
                    if ((ch[fa[y]][0]==y)^(ch[y][0]==x)) Rotate(x);
                        else Rotate(y);
                Rotate(x);
            }
    }
    inline void Access(int x) {for (int y=0; x; y=x,x=fa[x]) Splay(x),ch[x][1]=y;}
    inline void Link(int x,int y) {fa[x]=y; Access(y); Splay(y); Add(y,val[x]);}
    inline void Cut(int x) {Access(x); Splay(x); Add(ch[x][0],-val[x]); fa[ch[x][0]]=0,ch[x][0]=0;}
}using namespace LCT;
namespace SAM
{
    int son[MAXN][27],len[MAXN],par[MAXN];
    int root,last,sz;
    inline void Init() {root=last=sz=1;}
    inline void Extend(int c)
    {
        int cur=++sz,p=last;
        len[cur]=len[p]+1; LCT::val[cur]=1;
        while (p && !son[p][c]) son[p][c]=cur,p=par[p];
        if (!p) par[cur]=root,LCT::Link(cur,root);
        else
            {
                int q=son[p][c];
                if (len[p]+1==len[q]) par[cur]=q,LCT::Link(cur,q);
                else
                    {
                        int nq=++sz;
                        memcpy(son[nq],son[q],sizeof(son[nq]));
                        len[nq]=len[p]+1,par[nq]=par[q]; LCT::Link(nq,par[nq]);
                        while (p && son[p][c]==q) son[p][c]=nq,p=par[p];
                        par[cur]=par[q]=nq;
                        LCT::Cut(q); LCT::Link(cur,nq); LCT::Link(q,nq);
                    }
            }
        last=cur;
    }
    inline void Build() {Init(); for (int i=1; i<=N; i++) Extend(S[i]-'A'+1);}
    inline void Insert()
    {
        read(); M=strlen(S+1);
        for (int i=1; i<=M; i++) Extend(S[i]-'A'+1);
    }
    inline int Query()
    {
        read(); M=strlen(S+1);
        int now=root;
        for (int i=1; i<=M; i++)
            if (!son[now][S[i]-'A'+1]) return 0;
                else now=son[now][S[i]-'A'+1];
        LCT::Splay(now);
        return val[now];
    }
}using namespace SAM;
int main()
{
    scanf("%d",&Q);
    scanf("%s",S+1); N=strlen(S+1);
    SAM::Build();
    while (Q--)
        {
            char opt[10];
            scanf("%s%s",opt+1,S+1);
            switch (opt[1])
                {
                    case 'A' : SAM::Insert(); break;
                    case 'Q' : printf("%d
",ans=SAM::Query()); Mask^=ans; break;
                }
//            for (int i=1; i<=sz; i++) printf("%d %d %d %d
",i,ch[i][0],ch[i][1],val[i]);
        }
    return 0;
}
View Code

BZOJ 工艺

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
#define MAXN 600010
int N,ans[MAXN],A[MAXN];
namespace SAM
{
    int len[MAXN<<1],par[MAXN<<1],last,root,sz;
    map<int,int>son[MAXN<<1];
    map<int,int>::iterator it;
    inline void Init() {last=root=sz=1;}
    inline void Extend(int c)
    {
        int cur=++sz,p=last;
        len[cur]=len[p]+1;
        while (p && !son[p][c]) son[p][c]=cur,p=par[p];
        if (!p) par[cur]=root;
        else
            {
                int q=son[p][c];
                if (len[p]+1==len[q]) par[cur]=q;
                else
                    {
                        int nq=++sz;
                        son[nq]=son[q]; len[nq]=len[p]+1; par[nq]=par[q];
                        while (p && son[p][c]==q) son[p][c]=nq,p=par[p];
                        par[cur]=par[q]=nq;
                    }
            }
        last=cur;
    }
    inline void Build() {Init(); for (int i=1; i<=N; i++) Extend(A[i]);}
    inline void Query()
    {
        int tot=0,now=root;
        while (tot!=(N>>1))
            {
                it=son[now].begin();
                now=it->second;
                ans[++tot]=it->first;
            }
        printf("%d",ans[1]);
        for (int i=2; i<=tot; i++) printf(" %d",ans[i]); puts("");
    }
}using namespace SAM;
int main()
{
    N=read();
    for (int i=1; i<=N; i++) A[i+N]=A[i]=read();
    N<<=1;
    SAM::Build();
    SAM::Query();
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/6202373.html