【SPOJ8222】Substrings (后缀自动机)

题意:

给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值。

求F(1)..F(Length(S)) Length(S) <= 250000

思路:板子中st[x]定义为root到x的最多步数,可以用来更新所有长度为[1..st[x]]的答案

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 typedef unsigned int uint;
 5 typedef unsigned long long ull;
 6 typedef pair<int,int> PII;
 7 typedef pair<ll,ll> Pll;
 8 typedef vector<int> VI;
 9 typedef vector<PII> VII;
10 typedef pair<ll,int>P;
11 #define N  510000
12 #define M  151000
13 #define fi first
14 #define se second
15 #define MP make_pair
16 #define pi acos(-1)
17 #define mem(a,b) memset(a,b,sizeof(a))
18 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
19 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
20 #define lowbit(x) x&(-x)
21 #define Rand (rand()*(1<<16)+rand())
22 #define id(x) ((x)<=B?(x):m-n/(x)+1)
23 #define ls p<<1
24 #define rs p<<1|1
25
26 const int MOD=998244353,inv2=(MOD+1)/2;
27       double eps=1e-6;
28       ll INF=1e18;
29       ll inf=5e13;
30       int dx[4]={-1,1,0,0};
31       int dy[4]={0,0,-1,1};
32
33 char ch[N];
34 int n,i,x,p,q,np,nq,cnt,L,st[N],c[N][26],f[N],pos[N],bl[N],to[N],b[N],sz[N],ans[N];
35
36 int read()
37 {
38    int v=0,f=1;
39    char c=getchar();
40    while(c<48||57<c) {if(c==‘-‘) f=-1; c=getchar();}
41    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
42    return v*f;
43 }
44
45 void add(int x)
46 {
47     p=np;
48     st[np=++cnt]=st[p]+1;
49     to[np]=i;
50     pos[i]=np;
51     while(p&&!c[p][x])
52     {
53         c[p][x]=np;
54         p=f[p];
55     }
56     if(!p) f[np]=1;
57      else if(st[p]+1==st[q=c[p][x]]) f[np]=q;
58       else
59       {
60           st[nq=++cnt]=st[p]+1;
61           memcpy(c[nq],c[q],sizeof c[q]);
62           f[nq]=f[q];
63           f[q]=f[np]=nq;
64           while(p&&c[p][x]==q)
65           {
66               c[p][x]=nq;
67               p=f[p];
68           }
69       }
70 }
71
72
73 int main()
74 {
75     //freopen("1.in","r",stdin);
76     //freopen("1.out","w",stdout);
77     np=cnt=1;
78     scanf("%s",ch);
79     n=strlen(ch);
80     rep(i,0,n-1) add(ch[i]-‘a‘);
81     rep(i,1,cnt) b[st[i]]++;
82     rep(i,1,n) b[i]+=b[i-1];
83     rep(i,1,cnt) bl[b[st[i]]--]=i;
84     for(i=0,p=1;i<n;i++) sz[p=c[p][ch[i]-‘a‘]]++;
85     for(i=cnt;i;i--) sz[f[bl[i]]]+=sz[bl[i]];
86     //rep(i,0,n-1) printf("%d ",sz[pos[i]]);
87     rep(i,1,n) ans[i]=0;
88     rep(i,1,cnt) ans[st[i]]=max(ans[st[i]],sz[i]);
89     per(i,n-1,1) ans[i]=max(ans[i],ans[i+1]);
90     rep(i,1,n) printf("%d\n",ans[i]);
91     return 0;
92 }

原文地址:https://www.cnblogs.com/myx12345/p/11460908.html

时间: 2024-10-25 17:29:56

【SPOJ8222】Substrings (后缀自动机)的相关文章

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)],同时他的出

【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]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[tm

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

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】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

【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