SPOJ NSUBSTR 求每个对应的长度能产生的相同子串的最大个数
2017-10-24 19:40
344 查看
You are given a string S which consists of 250000 lowercase latin letters at most. We define F(x) as the maximal number of times that some string with length x appears in S. For example for string ‘ababa’ F(3) will be 2 because there is a string ‘aba’ that occurs twice. Your task is to output F(i) for every i so that 1<=i<=|S|.
Input
String S consists of at most 250000 lowercase latin letters.
Output
Output |S| lines. On the i-th line output F(i).
Example
Input:
ababa
Output:
3
2
2
1
1
给定一个字符串,求每个对应的长度能产生的相同子串的最大个数
后缀自动机 首先要得出所有长度的子串在总串中的出现次数,其实只要得出最大长度就好,其他的长度可以由 dp[len]=max(dp[len],dp[len+1]) 得到。
后缀自动机上每个节点代表可以接收的最大长度后缀。那么可以 利用子节点往父节点更新就好。因为子节点出现的地方父节点也必然会出现,最后扫一遍len就行
Input
String S consists of at most 250000 lowercase latin letters.
Output
Output |S| lines. On the i-th line output F(i).
Example
Input:
ababa
Output:
3
2
2
1
1
给定一个字符串,求每个对应的长度能产生的相同子串的最大个数
后缀自动机 首先要得出所有长度的子串在总串中的出现次数,其实只要得出最大长度就好,其他的长度可以由 dp[len]=max(dp[len],dp[len+1]) 得到。
后缀自动机上每个节点代表可以接收的最大长度后缀。那么可以 利用子节点往父节点更新就好。因为子节点出现的地方父节点也必然会出现,最后扫一遍len就行
#include <bits/stdc++.h> using namespace std; const int maxn = 500000+5; int last,tail,Min[maxn]; int Max[maxn],cnt[maxn],vis[maxn]; int nxt[maxn][26],fail[maxn]; char sa[maxn],sb[maxn]; int Maxi[maxn]; int sz[maxn]; int b[maxn]; inline void build(char *s) { while(*s) { int p=last,t=++tail,c=*s++-'a'; sz[t]=1; Max[t]=Max[p]+1; while(p&&!nxt[p][c]) nxt[p][c]=t,p=fail[p]; if(p) { int q=nxt[p][c]; if(Max[q]==Max[p]+1) fail[t]=q,Min[t]=Max[q]+1; else { int k=++tail; fail[k]=fail[q]; fail[t]=fail[q]=k; Max[k]=Max[p]+1; memcpy(nxt[k],nxt[q],sizeof(nxt[q])); while(p&&nxt[p][c]==q) nxt[p][c]=k,p=fail[p]; } } else fai 4000 l[t]=Min[t]=1; last=t; } } int q[maxn]; int f[maxn]; int main() { scanf("%s",sa); last=1,tail=1; build(sa); int len=strlen(sa); for(int i=1;i<=tail;i++) cnt[Max[i]]++; for(int i=1;i<=len;i++) cnt[i]+=cnt[i-1]; for(int i=1;i<=tail;i++) b[cnt[Max[i]]--]=i; for(int i=tail;i>=1;i--) sz[fail[b[i]]]+=sz[b[i]]; for(int i=1;i<=tail;i++) f[Max[i]]=max(f[Max[i]],sz[i]); for(int i=len;i>=1;i--) f[i]=max(f[i],f[i+1]); for(int i=1;i<=len;i++) printf("%d\n",f[i] ); }
相关文章推荐
- spoj 8222 NSUBSTR 求长度为x的子串中出现次数最大值 SAM
- SPOJ 694 / SPOJ DISUBSTR Distinct Substrings【后缀数组】不相同的子串的个数
- SPOJ DISUBSTR - Distinct Substrings(后缀数组[不相同的子串的个数])
- SPOJ - DISUBSTR Distinct Substrings(后缀数组求不相同的子串个数)
- 如果字符串的一个子串(其长度大于 1)的各个字符均相同,则称之为等值子串。试设计一算法,求出串S中的最大等值子串 函数返回最大等值子串的长度,如果没有则返回1。 例如: 若S= “abc123abc1
- java获取两个字符串中最大相同子串。第一个动作:将短的那个串进行长度一次递减的子串打印
- SPOJ - NSUBSTR(长度为1-len的字串出现的最大次数
- SPOJ 题目 8222 NSUBSTR - Substrings(后缀自动机+DP求子串出现最大次数)
- HDU4850 构造一个长度为n的串,要求任意长度为4的子串不相同
- java基础-找出两个字符串相同的最大子串
- 【CROC 2016 - Elimination RoundE】【DP】Intellectual Inquiry 长度为m字符串后添加n位最大本质不同子串个数
- 最大公共子串的长度模板
- Sting类中最大相同子串
- 求一个字符串的最长不重复子串的最大长度
- SPOJ PHRASES 每个字符串至少出现两次且不重叠的最长子串
- CF305 Mike and Feet 单调栈(求每个长度对应的最小数字)
- SPOJ694 -- DISUBSTR 后缀树组求不相同的子串的个数
- 求两个字符串的公共子串的最大长度
- 获取两个字符串中最大相同子串
- SPOJ 694. Distinct Substrings (不相同的子串的个数)