#1449 : 后缀自动机三·重复旋律6

时间限制:15000ms
单点时限:3000ms
内存限制:512MB

描述

小Hi平时的一大兴趣爱好就是演奏钢琴。我们知道一个音乐旋律被表示为一段数构成的数列。

现在小Hi想知道一部作品中所有长度为K的旋律中出现次数最多的旋律的出现次数。但是K不是固定的,小Hi想知道对于所有的K的答案。

解题方法提示

输入

共一行,包含一个由小写字母构成的字符串S。字符串长度不超过 1000000。

输出

共Length(S)行,每行一个整数,表示答案。

样例输入
aab
样例输出
2
1
1
  • 要求长度为k的子串中出现次数最多的串的出现次数
  • 对于每个节点代表的子串出现次数的求法是拓扑排序之后从len最大的逐步向前更新之前节点的出现次数
  • 原理是沿着par指针向前访问节点意味着访问的是同一最大子串的连续的子串
  • 比如长度最大的串是abcdef是len最大的节点表示的最长串,最短串是abcd,那么沿par指针访问前一个节点,那么前一个节点表示的子串是ab到abc,所以最长串出现多少次,沿par访问的串就会出现多少次
  • 在实际操作过程中对于extend操作中第一个新建的节点,打标记,意思当前串出现1次,而extend操作中衍生出的nq节点就标记为0
  • 自动机完成后就是对于自动机拓扑排序,用len长的更新len短的得到每一个节点代表子串出现次数,用ans[length]记录每个长度的最大出现次数
  • 但是要注意此时的ans数组不是最后答案,因为ans数组还要满足一个基本条件,即段子串出现次数一定比长子串出现次数多,就是说ans数组应该是一个非严格递减序列
  • 我们倒着遍历ans数组,ans[i]=max(ans[i],ans[i+1]);
  • 原因也好总结,因为后缀数组记录的len是匹配最大长度,我们没有记录minlen,所以对于一个节点出现次数我们没有更新对应的minlen对应长度的出现次数,就是说在不同自动机路径中我们没法保证把1到n长度子串出现次数全部一次性统计正确,因为会有路径上将很多长度的子串次数集中记录在最大的长度len上而没有对于小长度进行更新
 #include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
typedef long long LL ;
typedef unsigned long long ULL ;
const int maxn = 1e6 + ;
const int inf = 0x3f3f3f3f ;
const int npos = - ;
const int mod = 1e9 + ;
const int mxx = + ;
const double eps = 1e- ;
const double PI = acos(-1.0) ; struct cnode{
int len, st;
cnode(int x, int y){
len=x; st=y;
}
};
bool ccmp(const cnode l, const cnode r){
return l.len>r.len;
}
struct SAM{
int n, tot, root, last;
int cnt[maxn<<], ans[maxn];
struct node{
int len, flag;
int link, go[];
};
node state[maxn<<];
void init(char *str){
n=strlen(str);
tot=;
root=;
last=;
memset(&state,,sizeof(state));
}
void extend(int w){
tot++;
int p=last;
int np=tot;
state[np].len=state[p].len+;
state[np].flag=;
while(p && state[p].go[w]==){
state[p].go[w]=np;
p=state[p].link;
}
if(p==){
state[np].link=root;
}else{
int q=state[p].go[w];
if(state[p].len+==state[q].len){
state[np].link=q;
}else{
tot++;
int nq=tot;
state[nq].len=state[p].len+;
state[nq].flag=;
memcpy(state[nq].go,state[q].go,sizeof(state[q].go));
state[nq].link=state[q].link;
state[q].link=nq;
state[np].link=nq;
while(p && state[p].go[w]==q){
state[p].go[w]=nq;
p=state[p].link;
}
}
}
last=np;
}
void build(char *str){
init(str);
for(int i=;i<n;i++)
extend(str[i]-'a');
}
std::vector<cnode> v;
void solve(void){
v.clear();
for(int i=;i<=tot;i++){
cnt[i]=state[i].flag;
v.push_back(cnode(state[i].len,i));
}
sort(v.begin(),v.end(),ccmp);
for(int i=;i<v.size();i++){
cnt[state[v[i].st].link]+=cnt[v[i].st];
}
memset(ans,,sizeof(ans));
for(int i=;i<=tot;i++)
ans[state[i].len]=max(ans[state[i].len],cnt[i]);
for(int i=n-;i>;i--)
ans[i]=max(ans[i],ans[i+]);
for(int i=;i<=n;i++)
printf("%d\n",ans[i]);
}
};
SAM A;
char str[maxn];
int main(){
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
while(~scanf("%s",str)){
A.build(str);
A.solve();
}
return ;
}

hihoCoder_1449_后缀自动机三·重复旋律6的更多相关文章

  1. hihoCoder 后缀自动机三·重复旋律6

    后缀自动机三·重复旋律6 时间限制:15000ms 单点时限:3000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数列. 现在小Hi ...

  2. HihoCoder1449 后缀自动机三·重复旋律6

    描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数列. 现在小Hi想知道一部作品中所有长度为K的旋律中出现次数最多的旋律的出现次数.但是K不是固定的,小Hi想知道对 ...

  3. 【后缀自动机】hihocoder1449 后缀自动机三·重复旋律6

    解题方法提示 小Hi:上次我们已经学习了后缀自动机了,今天我们再来解决一个用到后缀自动机的问题. 小Ho:好!那我们开始吧! 小Hi:现在我们要对K=1..length(S)求出所有长度为K的子串中出 ...

  4. HIHOcoder 1449 后缀自动机三·重复旋律6

    思路 显然endpos的大小就对应了对应子串的出现次数,所以快速求出endpos的大小,然后用它更新对应子串长度(minlen[i]~maxlen[i])的答案即可 endpos的大小可以拓扑排序求出 ...

  5. hiho一下第129周 后缀自动机二·重复旋律6

    后缀自动机三·重复旋律6 时间限制:15000ms 单点时限:3000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数列. 现在小Hi ...

  6. BZOJ 后缀自动机四·重复旋律7

    后缀自动机四·重复旋律7 时间限制:15000ms 单点时限:3000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一段音乐旋律可以被表示为一段数构成的数列. 神奇的 ...

  7. hihoCoder #1445 : 后缀自动机二·重复旋律5

    #1445 : 后缀自动机二·重复旋律5 时间限制:10000ms 单点时限:2000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数 ...

  8. hiho一下122周 后缀数组三·重复旋律

    后缀数组三·重复旋律3 时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为长度为 N 的数构成的数列.小Hi ...

  9. HDU_1457_后缀自动机四·重复旋律7

    #1457 : 后缀自动机四·重复旋律7 时间限制:15000ms 单点时限:3000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一段音乐旋律可以被表示为一段数构成 ...

随机推荐

  1. (转)基于live555的流媒体代理转发服务器

    对于并发量并不大而且对性能要求不是很高的流媒体传输模块,live555还是很好的选择,下面说一下我所实现的流媒体代理服务器(目前只能实现对H264单视频的转发)代理转发主要 对于并发量并不大而且对性能 ...

  2. 在对listctrl的控件进行重载的过程中,GetHeaderCtrl()返回NULL的问题

    先谈谈我的问题吧! 在使用listctrl的过程中,我需要在列表头部添加checkbox,实现全选的功能. 经过网上资料的罗列,我找到了一个demo,使用的重绘的方法,在使用的过程中,我发现我的列表头 ...

  3. 初识Comet技术

    一.服务器推送技术概述 服务器推送技术(Servers Push)的基础思想是将浏览器主动查询信息改为服务器主动发送信息.服务器发送一批数据,浏览器显示这些数据,同时保证与服务器的连接.当服务器需要再 ...

  4. qlineedit控件获得焦点

    出处:http://blog.sina.com.cn/s/blog_640531380100wld9.html qlineedit控件获得焦点 lineEdit->setFocus();

  5. Uniprot 数据库-最常用的蛋白质数据库

    Uniprot 数据库是收录信息最全面的蛋白质数据库,包含swissport, uniparc, TrEMBL 3个子数据库: 其中swiss-prot 是手工核对过的 ,非冗余, 有详细注释信息的蛋 ...

  6. 【树莓派】GSM900模块

    python代码 https://github.com/JFF-Bohdan/sim-module

  7. The Rox Java NIO Tutorial

    FQ之后访问 http://rox-xmlrpc.sourceforge.net/niotut/

  8. React 生态系统:从小白到大神

    http://mp.weixin.qq.com/s/Epx46lznpnvgrIsbmAIZBA

  9. POJ 1691 Painting a Board(状态压缩DP)

    Description The CE digital company has built an Automatic Painting Machine (APM) to paint a flat boa ...

  10. [转载]Linux I/O 调度方法

    http://scoke.blog.51cto.com/769125/490546 IO调度器的总体目标是希望让磁头能够总是往一个方向移动,移动到底了再往反方向走,这恰恰就是现实生活中的电梯模型,所以 ...