spoj8222
地址:
题目:
NSUBSTR - Substrings
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
思路:
先求出每个状态的endpos集合大小,用cnt记录,用cnt[s]去更新f[len[s]],再用f[i+1]去更新f[i].
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 char ss[300004]; 6 int ans,f[300001<<1]; 7 8 struct SAM 9 { 10 static const int MAXN = 300001<<1;//大小为字符串长度两倍 11 static const int LetterSize = 26; 12 13 int tot, last, ch[MAXN][LetterSize], fa[MAXN], len[MAXN]; 14 int sum[MAXN], tp[MAXN], cnt[MAXN]; //sum,tp用于拓扑排序,tp为排序后的数组 15 16 void init( void) 17 { 18 last = tot = 1; 19 len[1] = 0; 20 memset(ch,0,sizeof ch); 21 memset(fa,0,sizeof fa); 22 memset(cnt,0,sizeof cnt); 23 } 24 25 void add( int x) 26 { 27 int p = last, np = last = ++tot; 28 len[np] = len[p] + 1, cnt[last] = 1; 29 while( p && !ch[p][x]) ch[p][x] = np, p = fa[p]; 30 if( p == 0) 31 fa[np] = 1; 32 else 33 { 34 int q = ch[p][x]; 35 if( len[q] == len[p] + 1) 36 fa[np] = q; 37 else 38 { 39 int nq = ++tot; 40 memcpy( ch[nq], ch[q], sizeof ch[q]); 41 len[nq] = len[p] + 1, fa[nq] = fa[q], fa[q] = fa[np] = nq; 42 while( p && ch[p][x] == q) ch[p][x] = nq, p = fa[p]; 43 } 44 } 45 } 46 47 void toposort( void) 48 { 49 for(int i = 1; i <= len[last]; i++) sum[i] = 0; 50 for(int i = 1; i <= tot; i++) sum[len[i]]++; 51 for(int i = 1; i <= len[last]; i++) sum[i] += sum[i-1]; 52 for(int i = 1; i <= tot; i++) tp[sum[len[i]]--] = i; 53 for(int i = tot; i; i--) cnt[fa[tp[i]]] += cnt[tp[i]]; 54 } 55 } sam; 56 57 58 int main(void) 59 { 60 //freopen("in.acm","r",stdin); 61 sam.init(); 62 scanf("%s",ss); 63 for(int i=0,len=strlen(ss);i<len;i++) sam.add(ss[i]-'a'); 64 sam.toposort(); 65 for(int i=1;i<=sam.tot;i++) f[sam.len[i]]=max(f[sam.len[i]],sam.cnt[i]); 66 for(int i=sam.len[sam.last];i;i--) f[i]=max(f[i],f[i+1]); 67 for(int i=1;i<=sam.len[sam.last];i++) printf("%d\n",f[i]); 68 return 0; 69 }
作者:weeping
出处:www.cnblogs.com/weeping/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。