spoj8222:Substrings 后缀自动机+DP
2016-03-22 16:20
288 查看
看后缀自动机看的真是生不如死,人太弱表示看不懂,现在还是没有完全理解啊。
这是一道SAM的入门题。
我们首先构造出SAM,然后SAM中每个节点i有一个righti和leni,那么长度在(lenfai,leni]内的都出现了righti次。考虑如果一个长度为leni的出现了x次,那么长度<leni的一定也至少出现了x次,所以我们可以直接算每个righti对leni的贡献。最后递推更新一下答案令fi=max(fi,fi+1)就好了。
现在还有一个问题没解决,就是righti的求法,我们只需要righti的大小而不需要集合内究竟是哪些数,所以可以开始给每个代表s[1..i]的节点i的righti=1,然后按深度合并一下,就能O(|S|)内求出所有的right了。
这是一道SAM的入门题。
我们首先构造出SAM,然后SAM中每个节点i有一个righti和leni,那么长度在(lenfai,leni]内的都出现了righti次。考虑如果一个长度为leni的出现了x次,那么长度<leni的一定也至少出现了x次,所以我们可以直接算每个righti对leni的贡献。最后递推更新一下答案令fi=max(fi,fi+1)就好了。
现在还有一个问题没解决,就是righti的求法,我们只需要righti的大小而不需要集合内究竟是哪些数,所以可以开始给每个代表s[1..i]的节点i的righti=1,然后按深度合并一下,就能O(|S|)内求出所有的right了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define N 500005 using namespace std; char s ; int S,n,cnt,last; int a[N],f[N],t[N],fa[N],cc[N],len[N],r[N],ch[N][26]; inline void insert(int x) { int c=a[x]; int p=last,np=++cnt; last=np; len[np]=x; while (p&&!ch[p][c]) ch[p][c]=np,p=fa[p]; if (!p) fa[np]=S; else { int q=ch[p][c]; if (len[p]+1==len[q]) fa[np]=q; else { int nq=++cnt; len[nq]=len[p]+1; memcpy(ch[nq],ch[q],sizeof(ch[q])); fa[nq]=fa[q]; fa[np]=fa[q]=nq; while (ch[p][c]==q) ch[p][c]=nq,p=fa[p]; } } } int main() { scanf("%s",s+1); last=S=++cnt; n=strlen(s+1); for (int i=1;i<=n;i++) a[i]=s[i]-'a'; for (int i=1;i<=n;i++) insert(i); for (int i=1,p=S;i<=n;i++) p=ch[p][a[i]],r[p]++; for (int i=1;i<=cnt;i++) ++cc[len[i]]; for (int i=1;i<=n;i++) cc[i]+=cc[i-1]; for (int i=1;i<=cnt;i++) t[cc[len[i]]--]=i; for (int i=cnt;i;i--) r[fa[t[i]]]+=r[t[i]]; for (int i=1;i<=cnt;i++) f[len[i]]=max(f[len[i]],r[i]); for (int i=n;i;i--) f[i]=max(f[i],f[i+1]); for (int i=1;i<=n;i++) printf("%d\n",f[i]); return 0; }
相关文章推荐
- linux C语言常见错误
- 手动配置hibernate5.1入门(1)
- intellij idea字体设置
- Android推送技术研究
- Java字符串:String使用详解及源码分析
- (嵌入式开发)自己写bootloader之编写第一阶段
- Spring JdbcTemplate方法详解
- 安装ECshop普遍问题的解决方法
- opencv图像特征检测之斑点检测
- Linux下SVN服务器搭建配置
- Android应用框架设计
- mac 下添加环境变量
- -canOpenURL: failed for URL
- 搜狐面试题:有12个球,外形都一样,其中有一个质量和其他的不一样,给你一架天平,请问最少称几次可以把那个不同的球找出来。
- python正则表达式模块,re.sub的函数使用
- 欢迎使用CSDN-markdown编辑器
- You must supply a resourceID for a TextView
- BZOJ 1190: [HNOI2007]梦幻岛宝珠
- 内部系统间调用client包的封装方法
- oracle中的游标