UVALive - 4811 Growing Strings (AC自动机+dp)

题目链接:UVALive - 4811 Growing Strings

题意:

给你n个字符串,问你最多能选出多少个字符串,使得s[i]是s[i+1]的子串。

题解:

先将所有的字符串插入AC自动机,将所有字符串按长度排序后,显然dp[i]=max{dp[j]}+1,其中s[j]是s[i]的子串。然后就完了。

 1 #include<bits/stdc++.h>
 2 #define mst(a,b) memset(a,b,sizeof(a))
 3 #define F(i,a,b) for(int i=(a);i<=(b);++i)
 4 using namespace std;
 5 
 6 const int AC_N=1e6+7,tyn=26;
 7 int n,dp[AC_N],ed,ans;
 8 char s[AC_N];
 9 struct Str
10 {
11     int l,len;
12     bool operator<(const Str &B)const{return len<B.len;}
13 }str[AC_N];
14 
15 struct AC_automation{
16     int tr[AC_N][tyn],cnt[AC_N],Q[AC_N],fail[AC_N],tot;
17     inline int getid(char x){return x-'a';}
18     void nw(){cnt[++tot]=0,fail[tot]=0;mst(tr[tot],0);}
19     void init(){tot=-1,fail[0]=-1,nw();}
20     void insert(char *s,int len,int idx,int x=0){
21         for(int i=0,w;i<len;x=tr[x][w],i++)
22             if(!tr[x][w=getid(s[i])])nw(),tr[x][w]=tot;
23         cnt[x]=idx;
24     }
25     void build(int head=1,int tail=0){
26         for(int i=0;i<tyn;i++)if(tr[0][i])Q[++tail]=tr[0][i];
27         while(head<=tail)for(int x=Q[head++],i=0;i<tyn;i++)
28             if(tr[x][i])fail[tr[x][i]]=tr[fail[x]][i],Q[++tail]=tr[x][i];
29             else tr[x][i]=tr[fail[x]][i];
30     }
31     int ask(char *s,int l,int &ans){
32         for(int x=0,i=0,w,j;i<l;i++){
33             x=tr[x][w=getid(s[i])];
34             for(j=x;j;j=fail[j])if(cnt[j])ans=max(ans,dp[cnt[j]]);
35         }
36         return ans;
37     }
38 }AC;
39 
40 int main(){
41     while(scanf("%d",&n),n)
42     {
43         ed=0,ans=1;
44         F(i,1,n)
45         {
46             scanf("%s",s+ed);
47             str[i]=Str{ed,(int)strlen(s+ed)};
48             ed+=str[i].len;
49         }
50         sort(str+1,str+1+n);
51         AC.init();
52         F(i,1,n)AC.insert(s+str[i].l,str[i].len,i);
53         AC.build(),dp[1]=1;
54         F(i,2,n)
55         {
56             dp[i]=0,AC.ask(s+str[i].l,str[i].len,dp[i]);
57             dp[i]++,ans=max(ans,dp[i]);
58         }
59         printf("%d\n",ans);
60     }
61     return 0;
62 }
View Code

 

posted @ 2017-07-29 10:22  bin_gege  阅读(111)  评论(0编辑  收藏  举报