●SPOJ 8222 NSUBSTR–Substrings(后缀自动机)
题链:
http://www.spoj.com/problems/NSUBSTR/
题解:
后缀自动机的水好深啊!
懂不了相关证明,带着结论把这个题做了。
看来这滩深水要以后再来了。
本题要用到一个叫 Right[P] 的数组,
表示 P对应的子串在原串中出现的所有位置的末尾位置下标的集合。
本题中,用这个数组存储集合大小就好了,即 P对应的子串在原串中出现了Right[p]次。
而Right[P]的值,等于从改点出发到结束状态的方案数。
但这个不好求,而是要用到另一个求法:用 Parent树:
(暂时由结论可知)Right集合不相交,只存在并列和包含关系。
所以把原来的 pre[]的指向反向后,形成一棵树,那么父节点的Right值=sigma(子节点节点的Right)
又因为这个Parent树无法遍历,且注意到儿子节点的step一定大于父亲节点的step,
所以对所有节点桶排序后,反向枚举,去更新父亲就好了。
计算出了Right[P]后,答案就可以统计了,详见代码。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 500100
#define filein(x) freopen(#x".in","r",stdin);
#define fileout(x) freopen(#x".out","w",stdout);
using namespace std;
struct SAM{
int size,last,q,p,nq,np,len;
int pre[MAXN],step[MAXN],Right[MAXN],ch[MAXN][26];
int Newnode(int a,int b){
step[size]=a; memcpy(ch[size],ch[b],sizeof(ch[b]));
return size++;
}
void Extend(int x){
p=last; last=np=Newnode(step[p]+1,0);
while(p&&!ch[p][x]) ch[p][x]=np,p=pre[p];
if(!p) pre[np]=1;
else{
q=ch[p][x];
if(step[q]!=step[p]+1){
nq=Newnode(step[p]+1,q);
pre[nq]=pre[q]; pre[q]=pre[np]=nq;
while(p&&ch[p][x]==q) ch[p][x]=nq,p=pre[p];
}
else pre[np]=q;
}
}
void Make_Right(char *S){
static int c[MAXN],T[MAXN]; p=1;
for(int i=0;i<len;i++) p=ch[p][S[i]-'a'],Right[p]++; memset(c,0,sizeof(c));
for(int i=1;i<size;i++) c[step[i]]++;
for(int i=1;i<=len;i++) c[i]+=c[i-1];
for(int i=1;i<size;i++) T[c[step[i]]--]=i; for(int i=size-1;i;i--) Right[pre[T[i]]]+=Right[T[i]];
}
void Build(char *S){
len=strlen(S); memset(ch[0],0,sizeof(ch[0]));
size=1; last=Newnode(0,0); pre[last]=0;
for(int i=0;i<len;i++) Extend(S[i]-'a');
Make_Right(S);
}
}suf;
int ANS[MAXN];
char S[MAXN];
int main()
{
scanf("%s",S);
int len=strlen(S);
suf.Build(S); for(int i=1;i<suf.size;i++) ANS[suf.step[i]]=max(ANS[suf.step[i]],suf.Right[i]);
for(int i=len-1;i;i--) ANS[i]=max(ANS[i],ANS[i+1]);
for(int i=1;i<=len;i++) printf("%d\n",ANS[i]);
return 0;
}
●SPOJ 8222 NSUBSTR–Substrings(后缀自动机)的更多相关文章
- ●SPOJ 8222 NSUBSTR - Substrings(后缀数组)
题链: http://www.spoj.com/problems/NSUBSTR/ 题解: 同届红太阳 --WSY给出的后缀数组解法!!! 首先用倍增算法求出 sa[i],rak[i],hei[i]然 ...
- SPOJ NSUBSTR Substrings 后缀自动机
人生第一道后缀自动机,总是值得纪念的嘛.. 后缀自动机学了很久很久,先是看CJL的论文,看懂了很多概念,关于right集,关于pre,关于自动机的术语,关于为什么它是线性的结点,线性的连边.许多铺垫的 ...
- SPOJ NSUBSTR Substrings ——后缀自动机
建后缀自动机 然后统计次数,只需要算出right集合的大小即可, 然后更新f[l[i]]和rit[i]取个max 然后根据rit集合短的一定包含长的的性质,从后往前更新一遍即可 #include &l ...
- ●SPOJ 8222 NSUBSTR–Substrings
题链: http://www.spoj.com/problems/NSUBSTR/题解: 后缀自动机. 不难发现,对于自动机里面的一个状态s, 如果其允许的最大长度为maxs[s],其right集合的 ...
- SPOJ 8222 NSUBSTR - Substrings
http://www.spoj.com/problems/NSUBSTR/ 题意: F(x)定义为字符串S中所有长度为x的子串重复出现的最大次数 输出F[1]~F[len(S)] 用字符串S构建后缀自 ...
- SPOJ8222 NSUBSTR - Substrings(后缀自动机)
You are given a string S which consists of 250000 lowercase latin letters at most. We define F(x) as ...
- 【刷题】SPOJ 8222 NSUBSTR - Substrings
You are given a string S which consists of 250000 lowercase latin letters at most. We define F(x) as ...
- SPOJ8222 NSUBSTR - Substrings 后缀自动机_动态规划
讲起来不是特别好讲.总之,如果 $dp[i+1]>=dp[i]$,故$dp[i]=max(dp[i],dp[i+1])$ Code: #include <cstdio> #inclu ...
- SP8222 NSUBSTR - Substrings(后缀自动机+dp)
传送门 解题思路 首先建出\(sam\),然后把\(siz\)集合通过拓扑排序算出来.对于每个点只更新它的\(maxlen\),然后再从大到小\(dp\)一次就行了.因为\(f[maxlen-1]&g ...
随机推荐
- Week02-Java基本语法与类库
1. 本周学习总结 本周主要学习了包装类,明白了包装类比基本数据类型的优点(见书面作业4.2),了解了自动装箱,自动拆箱的概念和区别(见书面作业4.1),知道了java中的引用类似C语言中的指针,明白 ...
- 201621123025《Java程序设计》第二周学习总结
1.本周学习总结 以几个关键词描述本周的学习内容.并将关键词之间的联系描述或绘制出来. 答:java的两种数据类型:基本数据类型和引用数据类型:==与equals的区别:动态数组. 2.书面作业 1. ...
- tornado httpserver
# coding:utf-8 import tornado.web import tornado.ioloop import tornado.httpserver # 新引入httpserver模块 ...
- 201621123068 Week02-Java基本语法与类库
1. 本周学习总结 1.1 当浮点数和整数放到一起运算时,java一般会将整数转化为浮点数然后进行浮点数计算,但是这样得出的结果通常与数学运算有一定误差,浮点数精确计算需要使用BigDecimal类 ...
- 《javascript设计模式与开发实践》阅读笔记(16)—— 状态模式
状态模式 会区分事物内部的状态,事物内部状态的改变往往会带来事物的行为改变.比如电灯的开关是开还是关,在外界的表现就完全不同. 电灯例子 按照常规思路,实现一个电灯就是构造一个电灯类,然后指定一下它的 ...
- Python内置函数(37)——sorted
英文文档: sorted(iterable[, key][, reverse]) Return a new sorted list from the items in iterable. Has tw ...
- JAVA版exe可执行加密软件
1.现在eclipse(myeclipse)中插入以下代码 1.1 MainForm package cee.hui.myfile; import javax.swing.*; import java ...
- Linux实战案例(3)创建和删除用户
建用户: adduser phpq //新建phpq用户passwd phpq //给php ...
- [八省联考2018] 劈配 mentor
Description 一年一度的综艺节目<中国新代码>又开始了.Zayid 从小就梦想成为一名程序员,他觉得这是一个展示自己的舞台,于是他毫不犹豫地报名了. Input 轻车熟路的Zay ...
- python常用运算符
1. / 浮点除法,就算分子分母都是int类型,也返回float类型,比如我们用4/2,返回2.0 2. // 整数除法,根据分子分母的不同组合,返回的值有差异. 正数//正数,取整,比如5//3,返 ...