zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    codeforces 666C Codeword
    codeforces 156D Clues(prufer序列)
    codeforces 633E Startup Funding(浮点数处理)
    codeforces 932E Team Work(组合数学、dp)
    codeforces 1000F One Occurrence(线段树、想法)
    codeforces 812E Sagheer and Apple Tree(思维、nim博弈)
    写点文字
    00000
    省选前干些奇怪的事情
    PE415
  • 原文地址:https://www.cnblogs.com/bin-gege/p/5823690.html
Copyright © 2011-2022 走看看