洛谷 P3804 模板后缀自动机

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 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 }

 

以上是关于洛谷 P3804 模板后缀自动机的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P3804 后缀自动机

P3804 模板后缀自动机

P3804 模板后缀自动机

P3804 后缀自动机模版

模板后缀自动机 (SAM)

109 后缀自动机(SAM)