[SPOJ8222]NSUBSTR - Substrings 后缀自动机

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 int sz=0,la,rt;
 6 int ch[500010][26],l[500010],fa[500010];
 7 void Extend(int c){
 8     int end=++sz,tmp=la;
 9     l[end]=l[tmp]+1;
10     while(tmp&&!ch[tmp][c]){
11         ch[tmp][c]=end;
12         tmp=fa[tmp];
13     }
14     if(!tmp) fa[end]=rt;
15     else{
16         int ne=ch[tmp][c];
17         if(l[ne]==l[tmp]+1) fa[end]=ne;
18         else{
19             int np=++sz;
20             memcpy(ch[np],ch[ne],sizeof(ch[ne]));
21             fa[np]=fa[ne];
22             l[np]=l[tmp]+1;
23             fa[ne]=fa[end]=np;
24             while(tmp&&ch[tmp][c]==ne){
25                 ch[tmp][c]=np;
26                 tmp=fa[tmp];
27             }
28         }
29     }
30     la=end;
31 }
32 char s[250010];
33 int r[500010],c[500010],a[500010],f[500010];
34 int main(){
35     rt=la=++sz;
36     scanf("%s",s+1);
37     int len=strlen(s+1);
38     for(int i=1;i<=len;i++){
39         r[sz+1]=1;
40         Extend(s[i]-‘a‘);
41     }
42     for(int i=1;i<=sz;i++) c[l[i]]++;
43     for(int i=1;i<=len;i++) c[i]+=c[i-1];
44     for(int i=1;i<=sz;i++) a[c[l[i]]--]=i;
45     for(int i=sz;i>=1;i--) r[fa[a[i]]]+=r[a[i]];
46     for(int i=1;i<=sz;i++) f[l[i]]=max(f[l[i]],r[i]);
47     for(int i=len;i>=1;i--) f[i]=max(f[i],f[i+1]);
48     for(int i=1;i<=len;i++) printf("%d\n",f[i]);
49     return 0;
50 }
时间: 2024-12-17 05:31:06

[SPOJ8222]NSUBSTR - Substrings 后缀自动机的相关文章

SPOJ8222 NSUBSTR - Substrings 后缀自动机_动态规划

讲起来不是特别好讲.总之,如果 $dp[i+1]>=dp[i]$,故$dp[i]=max(dp[i],dp[i+1])$ Code: #include <cstdio> #include <algorithm> #include <cstring> #define setIO(s) freopen(s".in","r",stdin) #define maxn 2000000 #define N 30 #define ll l

【CF316G3】Good Substrings 后缀自动机

[CF316G3]Good Substrings 题意:给出n个限制(p,l,r),我们称一个字符串满足一个限制当且仅当这个字符串在p中的出现次数在[l,r]之间.现在想问你S的所有本质不同的子串中,有多少个满足所有限制. |S|,|p|<=10^5,n<=10. 题解:比较简单的后缀自动机题,我们先把原串和所有限制串放到一起建一个广义后缀自动机,然后在pre树上统计一下即可得到每个子串在每个限制串中出现了多少次.现在我们想知道原串中有多少满足条件的子串,即我们统计一下所有出现次数符合要求的,

【POJ3415】Common Substrings 后缀自动机

转载请注明出处:http://blog.csdn.net/vmurder/article/details/42710069 其实我就是觉得原创的访问量比未授权盗版多有点不爽233... 题意: 给两个串,问有多少长度大于等于K的公共子串(位置不同也算一对) 题解: 后缀自动机DP 对第一个串建立后缀自动机,然后做一些预处理, 然后拿第二个串在后缀自动机上跑,到每个节点加一次贡献. 但是这样需要每个点往parent树上跑一遍,会TLE,所以可以加个lazy. 然后代码中有两次运用到拓扑序来从子向父

SPOJ8222 Substrings( 后缀自动机 + dp )

题目大意:给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值.F(1)..F(Length(S)) 建出SAM, 然后求出Right, 求Right可以按拓扑序dp..Right就是某个点到结束状态的路径数, parent树上last的那一条链都是结束状态...然后用Right去更新答案.. spoj卡常数..一开始用DFS就炸了, 改用BFS就A了.. (贴一下丽洁姐的题解: 我们构造S的SAM,那么对于一个节点s,它的长度范围是[Min(s),Max(s)],同时他的出

2019HNCPC C Distinct Substrings 后缀自动机

题意 给定一个长度为n字符串,字符集大小为m(1<=n,m<=1e6),求\(\bigoplus_{c = 1}^{m}\left(h(c) \cdot 3^c \bmod (10^9+7)\right)\)的值.其中h(c)为将c加到字符串末尾产生的新的本质不同的子串数目. 解题思路 比赛的时候没做出来,颁奖的时候听lts和lsx讲了之后发现可以用SAM做,而且板子稍微改改就可以了. 具体就是每次添加一个字符最多新建2个节点,根据SAM的性质,添加c后新建节点对本质不同的子串的数目的贡献就是

【SPOJ -NSUBSTR】Substrings 【后缀自动机+dp】

题意 给出一个字符串,要你找出所有长度的子串分别的最多出现次数. 分析 我们建出后缀自动机,然后预处理出每个状态的cnt,cnt[u]指的是u这个状态的right集合大小.我们设f[len]为长度为len的子串的最多出现次数.我们对于自动机的每个状态都更新f,f[st[u].len]=max(f[st[u].len],cnt[u]).然后这样更新完以后,可以神奇的dp一下.f[len]=max(f[len],f[len+1]).想想为什么? 1 #include <cstdio> 2 #inc

【SPOJ】8222. Substrings(后缀自动机)

http://www.spoj.com/problems/NSUBSTR/ 题意:给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值.求F(1)..F(Length(S)) 这题做法: 首先建立字符串的后缀自动机. 因为自动机中的每个状态都代表一类子串前缀,且任意状态的最长的|max|所对应的子串是唯一的. 所以我们算出每个子串(即找到的状态是end态),他们的right值为++(即保证长度为当前子串的出现次数为1),然后自底向上在parent树中更新right值(pare

SPOJ705 Distinct Substrings (后缀自动机&amp;后缀数组)

Given a string, we need to find the total number of its distinct substrings. Input T- number of test cases. T<=20;Each test case consists of one string, whose length is <= 1000 Output For each test case output one number saying the number of distinc

【SPOJ】Distinct Substrings(后缀自动机)

[SPOJ]Distinct Substrings(后缀自动机) 题面 Vjudge 题意:求一个串的不同子串的数量 题解 对于这个串构建后缀自动机之后 我们知道每个串出现的次数就是\(right/endpos\)集合的大小 但是实际上我们没有任何必要减去不合法的数量 我们只需要累加每个节点表示的合法子串的数量即可 这个值等于\(longest-shortest+1=longest-parent.longest\) #include<iostream> #include<cstdio&g