HDOJ-2296 AC自动机+DP..一定要细心..

来源:互联网 发布:撒切尔夫人 香港知乎 编辑:程序博客网 时间:2024/05/21 08:46

        构造Trie树..通过Trie树构造AC自动机..再通过AC自动机构造Trie图...

        本题DP的状态为dp[k][p].w 代表当字符串长度为k时..以头节点到p点为后缀的串所能得到的最大权值...同时用dp[k][p].s来存这个k长度的串..状态转移方向为Trie图中有向边的方向..显然k长度的状态只于k-1的状态有关..所以可以用滚动数组来存储dp状态..

        值得注意的是我以前做AC自动机DP时..在更新时没有考虑过用来更新的点在上一层是否有过更新...而本题是一定要考虑的..只有上一层更新过的点才能在当前层更新其沿有向边能到达的点...

        我有一个错误查了很久才解决..以后为了不出错..类似的DP在本层全部点更新完毕后,再来扫描所有点的权值更新ans吧...


贡献两组测试时自己出的数据:

TEST 1:14 2aabb3 3ans= aaaa    TEST 2:149 3loveufoevereveral12 7 3ans= aloveufoeveraloveufoeveraloveufoeveraloveufoever

Program:

#include<iostream>#include<stdio.h>#include<string.h>#include<queue>using namespace std;struct node1{       int son[26],fail,w;}point[1200];struct node2{       string s;       int w;}dp[2][1200];int T,m,n,w[102],i,j,num,h,k,x,len,t,ans;char s[15];string str,ans_str;queue<int> myqueue;bool used[1200];bool judge(string a,string b){       int la=a.length(),lb=b.length();       if (la!=lb) return la>lb;       return a>b;}int main(){       freopen("input.txt","r",stdin);       freopen("output.txt","w",stdout);       while (!myqueue.empty()) myqueue.pop();       scanf("%d",&T);       while (T--)       {             scanf("%d%d",&n,&m);             memset(point,0,sizeof(point));             num=0;             for (i=1;i<=m;i++)             {                   scanf("%s",s);                   len=strlen(s);                   h=0;                   for (j=0;j<len;j++)                   {                         if (!point[h].son[s[j]-'a'])                              point[h].son[s[j]-'a']=++num;                         h=point[h].son[s[j]-'a'];                    }                   point[h].w=i;             }             memset(w,0,sizeof(w));             for (i=1;i<=m;i++) scanf("%d",&w[i]);             for (i=0;i<26;i++)                if (point[0].son[i]) myqueue.push(point[0].son[i]);             while (!myqueue.empty())             {                   h=myqueue.front();                   myqueue.pop();                   point[h].w=w[point[h].w]+point[point[h].fail].w;                   for (i=0;i<26;i++)                   {                          k=point[h].fail;                          while (k && !point[k].son[i]) k=point[k].fail;                          point[point[h].son[i]].fail=point[k].son[i];                          if (point[h].son[i])                              myqueue.push(point[h].son[i]);                          else                              point[h].son[i]=point[k].son[i];                   }             }             k=0;             for (i=0;i<=num;i++)             {                   dp[k][i].w=0;                   dp[k][i].s="";             }             ans=0;  ans_str="";             while (n--)             {                    k=1-k;                   for (i=0;i<=num;i++)                   {                         dp[k][i].w=0;                         dp[k][i].s="";                   }                   memset(used,false,sizeof(used));                   used[0]=true;                   myqueue.push(0);                   while (!myqueue.empty())                   {                         h=myqueue.front();                         myqueue.pop();                          for (i=0;i<26;i++)                          {                                x=point[h].son[i];                                if (!used[x])                                {                                       used[x]=true;                                       myqueue.push(x);                                }                                if (h && dp[1-k][h].s=="") continue;                                if (dp[k][x].w>dp[1-k][h].w+point[x].w) continue;                                str=dp[1-k][h].s+char('a'+i);                                if (dp[k][x].w<dp[1-k][h].w+point[x].w ||                                    dp[k][x].s=="" || judge(dp[k][x].s,str))                                {                                       dp[k][x].w=dp[1-k][h].w+point[x].w;                                       dp[k][x].s=str;                                }                          }                   }                   for (h=0;h<=num;h++)                     if (dp[k][h].w>ans || dp[k][h].w==ans && judge(ans_str,dp[k][h].s))                     {                             ans=dp[k][h].w;                             ans_str=dp[k][h].s;                     }             }           //   printf("%d\n",ans);             len=ans_str.length();             for (i=0;i<len;i++) printf("%c",ans_str[i]);             printf("\n");       }       return 0;}