spoj 8222 Substrings(后缀自动机+DP)

 

Substrings
Time Limit: 100MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu

Submit Status

Description

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

 

【题意】

 

    给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值。求F(1)..F(Length(S))

 

【思路】

 

    先搞一个SAM。

    做法是将SAM上的结点拓扑一下,从后往前遍历,从子结点更新父结点(SAM上的pre其实并非是父结点)

最后还有一种情况便是子串完全包含的情况,也就是长度长的子串包含各种长度 短的子串

 

【代码】

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 const int N = 5*1e5+10;
 7 
 8 char s[N];
 9 int S,sz,last,ch[N][26],fa[N],l[N];
10 
11 void add(int x) {
12     int c=s[x]-'a';
13     int p=last,np=++sz; last=np;
14     l[np]=x;
15     for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
16     if(!p) fa[np]=S;
17     else {
18         int q=ch[p][c];
19         if(l[p]+1==l[q]) fa[np]=q;
20         else {
21             int nq=++sz; l[nq]=l[p]+1;
22             memcpy(ch[nq],ch[q],sizeof(ch[q]));
23             fa[nq]=fa[q];
24             fa[np]=fa[q]=nq;
25             for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
26         }
27     }
28 }
29 
30 int b[N],r[N],f[N],t[N];
31 
32 int main() {
33     scanf("%s",s+1);
34     last=S=++sz;
35     int len=strlen(s+1);
36     for(int i=1;i<=len;i++) add(i);
37     for(int i=1,p=S;i<=len;i++) {
38         p=ch[p][s[i]-'a']; r[p]++;
39     }
40     for(int i=1;i<=sz;i++) b[l[i]]++;
41     for(int i=1;i<=len;i++) b[i]+=b[i-1];
42     for(int i=1;i<=sz;i++) t[b[l[i]]--]=i;                 //基排 
43     for(int i=sz;i;i--) r[fa[t[i]]]+=r[t[i]];
44     for(int i=1;i<=sz;i++) f[l[i]]=max(f[l[i]],r[i]);
45     for(int i=len;i;i--) f[i]=max(f[i],f[i+1]);            //被包含的情况
46     for(int i=1;i<=len;i++) printf("%d\n",f[i]);
47     return 0;
48 }

 

你可能感兴趣的:(spoj 8222 Substrings(后缀自动机+DP))