• 洛谷 P3804 【模板】后缀自动机


    来一份模板

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<queue>
     5 using namespace std;
     6 typedef long long LL;
     7 char s[1000100];
     8 int n;
     9 LL ans;
    10 namespace SAM
    11 {
    12     int mem,np,root;
    13     int len[2000100],par[2000100];
    14     int trans[2000100][26];
    15     int in[2000100],sz[2000100];
    16     void append(int ch)
    17     {
    18         int p=np;np=++mem;len[np]=len[p]+1;
    19         for(;p&&!trans[p][ch];p=par[p])    trans[p][ch]=np;
    20         if(!p)    par[np]=root;
    21         else
    22         {
    23             int q=trans[p][ch];
    24             if(len[q]==len[p]+1)    par[np]=q;
    25             else
    26             {
    27                 int nq=++mem;par[nq]=par[q];par[q]=par[np]=nq;
    28                 memcpy(trans[nq],trans[q],sizeof(trans[nq]));len[nq]=len[p]+1;
    29                 for(;p&&trans[p][ch]==q;p=par[p])    trans[p][ch]=nq;
    30             }
    31         }
    32         sz[np]=1;
    33     }
    34     void build()
    35     {
    36         np=root=++mem;
    37         for(int i=1;i<=n;i++)    append(s[i]-'a');
    38     }
    39     queue<int> q;
    40     void work()
    41     {
    42         int i,t;
    43         for(i=1;i<=mem;i++)    ++in[par[i]];
    44         for(i=1;i<=mem;i++)
    45             if(!in[i])
    46                 q.push(i);
    47         while(!q.empty())
    48         {
    49             t=q.front();q.pop();
    50             if(sz[t]>1)    ans=max(ans,LL(sz[t])*len[t]);
    51             if(par[t])
    52             {
    53                 sz[par[t]]+=sz[t];
    54                 --in[par[t]];
    55                 if(!in[par[t]])    q.push(par[t]);
    56             }
    57         }
    58     }
    59 }
    60 
    61 int main()
    62 {
    63     scanf("%s",s+1);n=strlen(s+1);
    64     SAM::build();SAM::work();
    65     printf("%lld",ans);
    66     return 0;
    67 }

    还有后缀数组强行A此题

     1 #pragma GCC optimize("Ofast")
     2 #pragma GCC target("sse3","sse2","sse")
     3 #pragma GCC target("avx","sse4","sse4.1","sse4.2","ssse3")
     4 #pragma GCC target("f16c")
     5 #pragma GCC optimize("inline","fast-math","unroll-loops","no-stack-protector")
     6 #pragma GCC diagnostic error "-fwhole-program"
     7 #pragma GCC diagnostic error "-fcse-skip-blocks"
     8 #pragma GCC diagnostic error "-funsafe-loop-optimizations"
     9 #pragma GCC diagnostic error "-std=c++14"
    10 #include<cstdio>
    11 #include<algorithm>
    12 #include<cstring>
    13 #include<map>
    14 using namespace std;
    15 char s[1000100];
    16 int n;
    17 namespace SA
    18 {
    19     int sa[1000100],t1[1000100],t2[1000100],m='z',cnt[1000100],p;
    20     int *x=t1,*y=t2,*rk=t1,*height=t2;
    21     template<typename T>
    22     T get(int pos,T *a)
    23     {
    24         return pos<=n?a[pos]:0;
    25     }
    26     void build()
    27     {
    28         int i,k;int *it,*ed;
    29         for(i=1;i<=n;++i)    ++cnt[x[i]=s[i]];
    30         for(it=cnt+1,ed=cnt+m+1;it!=ed;++it)    *it+=*(it-1);
    31         for(i=n;i>=1;--i)    sa[cnt[x[i]]--]=i;
    32         for(k=1;k<=n;k<<=1)
    33         {
    34             p=0;
    35             for(i=n-k+1;i<=n;++i)    y[++p]=i;
    36             for(i=1;i<=n;++i)    if(sa[i]>k)  y[++p]=sa[i]-k;
    37             for(it=cnt+1,ed=cnt+m+1;it!=ed;++it)    *it=0;
    38             for(i=1;i<=n;++i)    cnt[x[y[i]]]++;
    39             for(it=cnt+1,ed=cnt+m+1;it!=ed;++it)    *it+=*(it-1);
    40             for(i=n;i>=1;--i)    sa[cnt[x[y[i]]]--]=y[i];
    41             swap(x,y);p=0;
    42             for(i=1;i<=n;++i)
    43                 x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&get(sa[i]+k,y)==get(sa[i-1]+k,y)
    44                     ?p:++p;
    45             if(p>=n) break;
    46             m=p;
    47         }
    48         for(i=1;i<=n;++i)    rk[sa[i]]=i;
    49         for(i=1,k=1;i<=n;++i)
    50         {
    51             if(k)   k--;
    52             if(rk[i])
    53                 while(get(sa[rk[i]-1]+k,s)==get(i+k,s)) k++;
    54             height[rk[i]]=k;
    55         }
    56     }
    57 }
    58 int sz[1000100],fa[1000100];
    59 int find(int x)    {return x==fa[x]?x:fa[x]=find(fa[x]);}
    60 typedef pair<int,int> P;
    61 typedef long long LL;
    62 P tmp[1000100];
    63 LL ans;
    64 bool cmp(const P& a,const P& b)
    65 {
    66     return a>b;
    67 }
    68 int main()
    69 {
    70     int i,d,t,fx,fy;
    71     scanf("%s",s+1);n=strlen(s+1);SA::build();
    72     for(i=1;i<=n;i++)    fa[i]=i,sz[i]=1;
    73     for(i=2;i<=n;i++)    tmp[i]=P(SA::height[i],i);
    74     sort(tmp+2,tmp+n+1,cmp);
    75     for(i=2;i<=n;i++)
    76     {
    77         d=tmp[i].first;t=tmp[i].second;
    78         fx=find(t-1);fy=find(t);
    79         sz[fy]+=sz[fx];fa[fx]=fy;
    80         ans=max(ans,LL(sz[fy])*d);
    81     }
    82     printf("%lld",ans);
    83     return 0;
    84 }

    以下是作死用map之后T掉的程序

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<map>
     5 #include<queue>
     6 using namespace std;
     7 typedef long long LL;
     8 char s[1000100];
     9 int n;
    10 LL ans;
    11 namespace SAM
    12 {
    13     int mem,np,root;
    14     int len[2000100],par[2000100];
    15     map<int,int> trans[2000100];
    16     int in[2000100],sz[2000100];
    17     void append(int ch)
    18     {
    19         int p=np;np=++mem;len[np]=len[p]+1;
    20         for(;p&&!trans[p].count(ch);p=par[p])    trans[p][ch]=np;
    21         if(!p)    par[np]=root;
    22         else
    23         {
    24             int q=trans[p][ch];
    25             if(len[q]==len[p]+1)    par[np]=q;
    26             else
    27             {
    28                 int nq=++mem;par[nq]=par[q];par[q]=par[np]=nq;
    29                 trans[nq]=trans[q];len[nq]=len[p]+1;
    30                 for(;p&&trans[p].count(ch)&&trans[p][ch]==q;p=par[p])    trans[p][ch]=nq;
    31             }
    32         }
    33         sz[np]=1;
    34     }
    35     void build()
    36     {
    37         np=root=++mem;
    38         for(int i=1;i<=n;i++)    append(s[i]-'a');
    39     }
    40     queue<int> q;
    41     void work()
    42     {
    43         int i,t;
    44         for(i=1;i<=mem;i++)    ++in[par[i]];
    45         for(i=1;i<=mem;i++)
    46             if(!in[i])
    47                 q.push(i);
    48         while(!q.empty())
    49         {
    50             t=q.front();q.pop();
    51             if(sz[t]>1)    ans=max(ans,LL(sz[t])*len[t]);
    52             if(par[t])
    53             {
    54                 sz[par[t]]+=sz[t];
    55                 --in[par[t]];
    56                 if(!in[par[t]])    q.push(par[t]);
    57             }
    58         }
    59     }
    60 }
    61 
    62 int main()
    63 {
    64     scanf("%s",s+1);n=strlen(s+1);
    65     SAM::build();SAM::work();
    66     printf("%lld",ans);
    67     return 0;
    68 }
  • 相关阅读:
    Callable Future 和 FutureTask
    多线程常用工具类
    Servlet的forward与include方法
    Spring MVC 执行流程分析
    使用SpringEL表达式进行三目运算
    推荐10款Java程序员使用的单元测试工具
    使用SpringEL表达式进行方法调用
    使用SpringEL操作List和Map集合
    SpringEL表达式(一)-入门案例
    Servlet的生命周期
  • 原文地址:https://www.cnblogs.com/hehe54321/p/8716607.html
Copyright © 2020-2023  润新知