spoj 8222 NSUBSTR 求长度为x的子串中出现次数最大值 SAM
题目大意
给一个字符串S
令F(x)表示S的所有长度为x的子串中
出现次数的最大值。
求F(1)..F(Length(S))
分析
一个节点\(x\)的长度有\(~~(max(fa),max(x)]\)
出现次数为\(|Right(x)|\)
则\((max(fa),max(x)]\)的出现次数都\(\ge |Right(x)|\)
做法
注意到对于一个点\(x\)的祖先链,长度是[1..max(fa)]
而且他们的\(|Right()|\)都\(\ge |Right(x)|\)
所有更新时对于\(x\)我们直接更新\([1...max(x)]是可以的\)
只更新到\(max(x)\),像后缀和那样求答案就好了
solution
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
using namespace std;
const int M=524288;
int go[M][26];
int fa[M];
int stp[M];
int sum[M];
int pos[M];
int right[M];
int last,tot;
char s[M];
int mx[M];
int n;
int newnode(int ss){
stp[++tot]=ss;
return tot;
}
int ext(int p,int q,int d){
int nq=newnode(stp[p]+1);
fa[nq]=fa[q];
fa[q]=nq;
memcpy(go[nq],go[q],sizeof(go[q]));
for(;p&&go[p][d]==q;p=fa[p]) go[p][d]=nq;
return nq;
}
int sam(int p,int d){
int np=go[p][d];
if(np) return (stp[p]+1==stp[np]) ? np : ext(p,np,d);
else{
np=newnode(stp[p]+1);
right[np]=1;
for(;p&&!go[p][d];p=fa[p]) go[p][d]=np;
if(!p) fa[np]=1;
else{
int q=go[p][d];
fa[np]= (stp[p]+1==stp[q]) ? q : ext(p,q,d);
}
}
return np;
}
int main(){
int i;
scanf("%s",s+1);
n=strlen(s+1);
last=tot=1;
for(i=1;i<=n;i++) last=sam(last,s[i]-'a');
for(i=1;i<=tot;i++) sum[stp[i]]++;
for(i=1;i<=n;i++) sum[i]+=sum[i-1];
for(i=1;i<=tot;i++) pos[sum[stp[i]]--]=i;
for(i=tot;i>0;i--) right[fa[pos[i]]]+=right[pos[i]];
for(i=1;i<=tot;i++) mx[stp[i]]=max(mx[stp[i]],right[i]);
for(i=n;i>0;i--) mx[i]=max(mx[i],mx[i+1]);
for(i=1;i<=n;i++) printf("%d\n",mx[i]);
return 0;
}
spoj 8222 NSUBSTR 求长度为x的子串中出现次数最大值 SAM的更多相关文章
- SPOJ 8222 NSUBSTR(SAM)
这几天看了N多论文研究了下后缀自己主动机.刚開始蛋疼的看着极短的代码和clj的论文硬是看不懂,后来结合其它几篇论文研究了下.总算是明确了一些 推荐文章http://blog.sina.com.cn/s ...
- LCS模板,求长度,并记录子串
//LCS模板,求长度,并记录子串 //亦可使用注释掉的那些代码,但所用空间会变大 #include<iostream> #include<cstring> #include ...
- ●SPOJ 8222 NSUBSTR - Substrings(后缀数组)
题链: http://www.spoj.com/problems/NSUBSTR/ 题解: 同届红太阳 --WSY给出的后缀数组解法!!! 首先用倍增算法求出 sa[i],rak[i],hei[i]然 ...
- SPOJ 8222 NSUBSTR - Substrings
http://www.spoj.com/problems/NSUBSTR/ 题意: F(x)定义为字符串S中所有长度为x的子串重复出现的最大次数 输出F[1]~F[len(S)] 用字符串S构建后缀自 ...
- 【刷题】SPOJ 8222 NSUBSTR - Substrings
You are given a string S which consists of 250000 lowercase latin letters at most. We define F(x) as ...
- 【uva11855-求长度为1到n的相同子串出现的次数】sam
题意:求长度为1到n的相同子串出现的次数,输到小于2为止. 题解: 用sam做. 建机,算right集合,然后用r[i]更新长度为step[i]的子串出现次数,然后ans[i]=maxx(ans[i] ...
- ●SPOJ 8222 NSUBSTR–Substrings
题链: http://www.spoj.com/problems/NSUBSTR/题解: 后缀自动机. 不难发现,对于自动机里面的一个状态s, 如果其允许的最大长度为maxs[s],其right集合的 ...
- ●SPOJ 8222 NSUBSTR–Substrings(后缀自动机)
题链: http://www.spoj.com/problems/NSUBSTR/ 题解: 后缀自动机的水好深啊!懂不了相关证明,带着结论把这个题做了.看来这滩深水要以后再来了. 本题要用到一个叫 R ...
- spoj 8222 Substrings (后缀自动机)
spoj 8222 Substrings 题意:给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值.求F(1)..F(Length(S)) 解题思路:我们构造S的SAM,那么对于 ...
随机推荐
- 第18题:在O(1)时间删除链表结点+删除链表中重复的节点
题目描述:题目描述在O(1)时间删除链表结点 给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点. 考查创新编程能力. 思路: 1.如果从头到尾遍历,时间O(n) 2.如果将待删 ...
- 你不知道的c++11
随着C++11的发布,C++这门语言有了本质上的提升.C++14,C++17的相继推出,更是让C++这门语言达到了一个新高度.新的标准库设施,新的语法,让我们得以书写更加安全.便捷.高效的程序. 20 ...
- python实现批量修改文件名
import os def dele(): # 设置一个计数器 n=0 st = input('请输入你要删除的字符:') for i in f: b = f[n] if st in b: oldna ...
- Session 会话保持
本文将详细讨论session的工作机制并且对在Java web application中应用session机制时常见的问题作出解答 一.术语session session,中文经常翻译为会话,其本来的 ...
- vue购物车的实现
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- (原创)task和function语法的使用讨论(Verilog,CPLD/FPGA)
1. Abstract function和task语句的功能有很多的相似之处,在需要有多个相同的电路生成时,可以考虑使用它们来实现.因为个人使用它们比较少,所以对它们没有进行更深的了解,现在时间比较充 ...
- git初次建立远程仓库问题
git "Could not read from remote repository.Please make sure you have the correct access rights. ...
- Codeforces Round #464 (Div. 2) B. Hamster Farm
B. Hamster Farm time limit per test2 seconds memory limit per test256 megabytes Problem Description ...
- 水题:HDU1303-Doubles
Doubles Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Su ...
- 51nod_1445 变色DNA 最短路模板 奇妙思维
这是一道最短路模板题,但是在理解题意和提出模型的阶段比较考验思维,很容易想到并且深深进入暴力拆解题目的无底洞当中. 题意是说:给出一个邻接矩阵,在每个点时,走且仅走向,合法路径中编号最小的点.问题是是 ...