码迷,mamicode.com
首页 > 其他好文 > 详细

【SPOJ -NSUBSTR】Substrings 【后缀自动机+dp】

时间:2018-10-31 12:42:43      阅读:211      评论:0      收藏:0      [点我收藏+]

标签:pac   cli   sub   onclick   子串   iostream   spl   int   strlen   

题意

 给出一个字符串,要你找出所有长度的子串分别的最多出现次数。

分析

  我们建出后缀自动机,然后预处理出每个状态的cnt,cnt[u]指的是u这个状态的right集合大小。我们设f[len]为长度为len的子串的最多出现次数。我们对于自动机的每个状态都更新f,f[st[u].len]=max(f[st[u].len],cnt[u])。然后这样更新完以后,可以神奇的dp一下。f[len]=max(f[len],f[len+1]).想想为什么?

 

技术分享图片
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5 
 6 using namespace std;
 7 const int maxn=250000+100;
 8 char s[maxn];
 9 int n;
10 struct state{
11     int len,link;
12     int ch[26];
13 }st[maxn*2];
14 int sz,last,cur,cnt[2*maxn],c[2*maxn],f[maxn];
15 void init(){
16     cur=last=0;
17     sz=1;
18     st[0].link=-1;
19     st[0].len=0;
20     memset(st[0].ch,-1,sizeof(st[0].ch));
21 }
22 void build_sam(int c){
23     cur=sz++;
24     st[cur].len=st[last].len+1;
25     cnt[cur]=1;
26     memset(st[cur].ch,-1,sizeof(st[cur].ch));
27     int p;
28     for(p=last;p!=-1&&st[p].ch[c]==-1;p=st[p].link)
29         st[p].ch[c]=cur;
30     if(p==-1)
31         st[cur].link=0;
32     else{
33         int q=st[p].ch[c];
34         if(st[q].len==st[p].len+1)
35             st[cur].link=q;
36         else{
37             int clone=sz++;
38             st[clone].len=st[p].len+1;
39             st[clone].link=st[q].link;
40             for(int i=0;i<26;i++)
41                 st[clone].ch[i]=st[q].ch[i];
42             for(;p!=-1&&st[p].ch[c]==q;p=st[p].link)
43                 st[p].ch[c]=clone;
44             st[q].link=st[cur].link=clone;
45         }
46     }
47     last=cur;
48 }
49 int cmp(int a,int b){
50     return st[a].len>st[b].len;
51 }
52 int main(){
53     scanf("%s",s);
54     n=strlen(s);
55     init();
56     for(int i=0;i<n;i++)
57         build_sam(s[i]-a);
58     for(int i=0;i<sz;i++)
59         c[i]=i;
60     sort(c,c+sz,cmp);
61 //    for(int i=0;i<sz;i++){
62 //        printf("%d\n",st[i].link);
63 //    }
64 //    printf("!!\n");
65 
66     for(int i=0;i<sz;i++){
67         int o=c[i];
68         cnt[st[o].link]+=cnt[o];
69     }
70 //    for(int i=0;i<sz;i++)
71 //        printf("%d ",cnt[i]);
72 //    printf("\n");
73 
74     for(int i=0;i<sz;i++)
75         f[st[i].len]=max(f[st[i].len],cnt[i]);
76     for(int i=n-1;i>=1;i--)
77         f[i]=max(f[i],f[i+1]);
78     for(int i=1;i<=n;i++){
79         printf("%d\n",f[i]);
80     }
81 return 0;
82 }
View Code

 

【SPOJ -NSUBSTR】Substrings 【后缀自动机+dp】

标签:pac   cli   sub   onclick   子串   iostream   spl   int   strlen   

原文地址:https://www.cnblogs.com/LQLlulu/p/9882228.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!