洛谷 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 }

原文地址:https://www.cnblogs.com/hehe54321/p/8716607.html

时间: 2024-08-30 14:41:28

洛谷 P3804 【模板】后缀自动机的相关文章

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

Portal Description 模板题啦~ 推荐WJMZBMR在WC2012上的讲义<后缀自动机>. Code //[模板]后缀自动机 #include <cstdio> int max(int x,int y) {return x>y?x:y;} int const N=2e6+10; int n; char s[N]; int rt,ndCnt,last; int fa[N],ch[N][26],len[N],siz[N]; void ins(int x) { in

洛谷 P3804 后缀自动机

题目描述 给定一个只包含小写字母的字符串SS , 请你求出 SS 的所有出现次数不为 11 的子串的出现次数乘上该子串长度的最大值. 输入输出格式 输入格式: 一行一个仅包含小写字母的字符串SS 输出格式: 一个整数,为 所求答案 输入输出样例 输入样例#1: abab 输出样例#1: 4 说明 对于10\%10% 的数据,|S|<=1000∣S∣<=1000 对于100\%100% 的数据,|S|<=10^6∣S∣<=106 今天上午恶补了一下后缀自动机,发现好像没有想象中的那么

AC自动机(附洛谷P3769模板题)

首先,介绍一下AC自动机(Aho-Corasick automaton),是一种在一个文本串中寻找每一个已给出的模式串的高效算法. 在学习AC自动机之前,你需要先学习Trie树和KMP算法,因为AC自动机正式利用并结合了两者的思想. 说到实际的不同,其实AC自动机只是在Trie树上引入了一个类似KMP中next数组的东西叫做Fail指针. 对于每一个节点,Fail指针指向该节点所代表的字符串中,次长的.在Trie树中存在的后缀(因为最长的在Trie树种存在的后缀就是其本身)所代表的节点. 举例:

【C++】最近公共祖先LCA(Tarjan离线算法)&amp;&amp; 洛谷P3379LCA模板

1.前言 首先我们介绍的算法是LCA问题中的离线算法-Tarjan算法,该算法采用DFS+并查集,再看此算法之前首先你得知道并查集(尽管我相信你如果知道这个的话肯定是知道并查集的),Tarjan算法的优点在于相对稳定,时间复杂度也比较居中,也很容易理解(个人认为). 2.思想 下面详细介绍一下Tarjan算法的思想: 1.任选一个点为根节点,从根节点开始. 2.遍历该点u所有子节点v,并标记这些子节点v已被访问过. 3.若是v还有子节点,返回2,否则下一步. 4.合并v到u上. 5.寻找与当前点

洛谷P3375 [模板]KMP字符串匹配

To 洛谷.3375 KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了. 输入输出格式 输入格式: 第一行为一个字符串,即为s1(仅包含大写字母) 第二行为一个字符串,即为s2(仅包含大写字母) 输出格式: 若干行,每行包含一个整数,表示s2在s1中出现的位置 接下来1行,包括length(s2)个整

洛谷.3803.[模板]多项式乘法(FFT)

题目链接:洛谷.LOJ. FFT相关:快速傅里叶变换(FFT)详解.FFT总结.从多项式乘法到快速傅里叶变换. #include <cmath> #include <cctype> #include <cstdio> #include <algorithm> #define gc() getchar() const int N=1e6+5; const double PI=acos(-1); int n,m; struct Complex { double

洛谷.1919.[模板]A乘B Problem升级版(FFT)

题目链接:洛谷.BZOJ2179 //将乘数拆成 a0*10^n + a1*10^(n-1) + ... + a_n-1的形式 //可以发现多项式乘法就模拟了竖式乘法 所以用FFT即可 注意处理进位 //n位*n位最多就只有2n位了 //论putchar的速度..还是快的 #include <cmath> #include <cstdio> #include <cctype> #include <algorithm> #define gc() getchar

[模板]后缀自动机

传送门 Description 给定一个只包含小写字母的字符串\(S\), 请你求出 \(S\) 的所有出现次数不为 \(1\) 的子串的出现次数乘上该子串长度的最大值. Solution 保持好习惯吧,模板题还是放一下 SAM的板子,想必是到处都有,反正都比我写的好看... 当初想学SAM的时候,就被某俄文翻译的\(20000\)字论文吓跑了... 核心? 作为一种可以表示所有后缀的状态的自动机,它得满足状态数尽可能的小 SAM的做法: 每个状态表示所有\(Right\)集合相同的子串,这里\

洛谷 [P2483] [模板] k短路

人生中的第一道黑题... 其实就是k短路模板 #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <cstdlib> #include <queue> using namespace std; const int MAXN=400005; int init(){ int