hdu_2296_Ring(AC自动机+DP)

题目链接:hdu_2296_Ring

题意:

有m个字符串,每个字符串有一个价值,现在让你组成一个不超过n长度的字符串,使得价值最大

题解:

很明显是在AC自动机上的DP,设dp[i][j]表示当前长度为i,AC自动机上匹配到j这个节点的最大价值,这里要求字典序最小,处理的稍微复杂一点,具体看代码

 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=a;i<=b;i++)
 3 using namespace std;
 4 
 5 const int AC_N=110*20,tyn=26;//数量乘串长,类型数
 6 struct AC_automation{
 7     int tr[AC_N][tyn],cnt[AC_N],Q[AC_N],fail[AC_N],tot;
 8     inline int getid(char x){return x-'a';}
 9     void nw(){cnt[++tot]=0,fail[tot]=0;memset(tr[tot],0,sizeof(tr[tot]));}
10     void init(){tot=-1,fail[0]=-1,nw();}
11     void insert(char *s,int val,int x=0){
12         for(int len=strlen(s),i=0,w;i<len;x=tr[x][w],i++)
13             if(!tr[x][w=getid(s[i])])nw(),tr[x][w]=tot;
14         cnt[x]=val;//串尾标记
15     }
16     void build(int head=1,int tail=0){
17         for(int i=0;i<tyn;i++)if(tr[0][i])Q[++tail]=tr[0][i];
18         while(head<=tail)for(int x=Q[head++],i=0;i<tyn;i++)
19             if(tr[x][i])fail[tr[x][i]]=tr[fail[x]][i],Q[++tail]=tr[x][i],cnt[tr[x][i]]+=cnt[tr[fail[x]][i]];
20             else tr[x][i]=tr[fail[x]][i];
21     }
22 }AC;
23 
24 char s[110][20];
25 string path[51][AC_N];
26 int t,n,m,x,dp[51][AC_N];
27 
28 void fuck(int ans=0)
29 {
30     memset(dp,-1,sizeof(dp)),dp[0][0]=0;
31     F(i,0,n)F(j,0,AC.tot)path[i][j].clear();
32     F(i,0,n-1)F(j,0,AC.tot)if(dp[i][j]!=-1)F(k,0,25)
33     {
34         int now=AC.tr[j][k];
35         if(dp[i][j]+AC.cnt[now]>dp[i+1][now])
36         {
37             dp[i+1][now]=dp[i][j]+AC.cnt[now];
38             path[i+1][now]=path[i][j]+(char)(k+'a');
39         }else if(dp[i][j]+AC.cnt[now]==dp[i+1][now]&&path[i][j]+(char)(k+'a')<path[i+1][now])
40                     path[i+1][now]=path[i][j]+(char)(k+'a');
41     }
42     F(i,1,n)F(j,0,AC.tot)ans=max(ans,dp[i][j]);
43     if(ans==0){puts("");return;}
44     string str=" ";
45     F(i,1,n)F(j,0,AC.tot)if(dp[i][j]==ans&&(str==" "||(path[i][j].size()<str.size()||(path[i][j].size()==str.size()&&path[i][j]<str))))str=path[i][j];
46     cout<<str<<endl;
47 }
48 
49 int main()
50 {
51     scanf("%d",&t);
52     while(t--)
53     {
54         scanf("%d%d",&n,&m);
55         AC.init();
56         F(i,1,m)scanf("%s",s[i]);
57         F(i,1,m)scanf("%d",&x),AC.insert(s[i],x);
58         AC.build(),fuck();
59     }
60     return 0;
61 }
View Code

 

posted @ 2016-08-30 21:24  bin_gege  阅读(146)  评论(0编辑  收藏  举报