HDU 2296 Ring AC自动机 + DP

题意:给你n个模式串,每个模式串有一个得分,让你构造出一个长度为N之内且分数最高的文本串;输出字典序列最小的。

解题思路:  AC自动机 + DP , 不过要输出字典序列最小,多开一个 一个三维字符串来辅助二维DP(新思路) , DP[i][j] ,表示到i位置状态为j的最大得分。

解题代码:

  1 // File Name: temp.cpp
  2 // Author: darkdream
  3 // Created Time: 2014年09月11日 星期四 15时18分4秒
  4
  5 #include<vector>
  6 #include<list>
  7 #include<map>
  8 #include<set>
  9 #include<deque>
 10 #include<stack>
 11 #include<bitset>
 12 #include<algorithm>
 13 #include<functional>
 14 #include<numeric>
 15 #include<utility>
 16 #include<sstream>
 17 #include<iostream>
 18 #include<iomanip>
 19 #include<cstdio>
 20 #include<cmath>
 21 #include<cstdlib>
 22 #include<cstring>
 23 #include<ctime>
 24 #include<queue>
 25 #define LL long long
 26 #define maxn 20000
 27 using namespace std;
 28
 29 int n,m;
 30 char str[55][1110][55];
 31 struct Trie
 32 {
 33     int next[maxn][26],fail[maxn],end[maxn];
 34     int root,L;
 35     int newnode()
 36     {
 37         memset(next[L],-1,sizeof(next[L]));
 38         end[L++] = 0;
 39         return L-1;
 40     }
 41     void init()
 42     {
 43         L = 0;
 44         root = newnode();
 45     }
 46     void insert(char buf[],int id)
 47     {
 48         int len = strlen(buf);
 49         int now = root;
 50         for(int i = 0;i < len ;i++)
 51         {
 52             if(next[now][buf[i]-‘a‘] == -1)
 53             {
 54                 next[now][buf[i]-‘a‘] = newnode();
 55             }
 56             now = next[now][buf[i]-‘a‘];
 57         }
 58         end[now] = id;
 59     }
 60     void build()
 61     {
 62         queue<int>Q;
 63         fail[root] = root;
 64         for(int i = 0;i < 26;i++)
 65             if(next[root][i] == -1)
 66                 next[root][i] = root;
 67             else
 68             {
 69                 fail[next[root][i]] = root;
 70                 Q.push(next[root][i]);
 71             }
 72         while( !Q.empty() )
 73         {
 74             int now = Q.front();
 75             Q.pop();
 76             if(end[fail[now]] == -1)end[now] = -1;
 77             else end[now] |= end[fail[now]];
 78             for(int i = 0;i < 26;i++)
 79                 if(next[now][i] == -1)
 80                     next[now][i] = next[fail[now]][i];
 81                 else
 82                 {
 83                     fail[next[now][i]] = next[fail[now]][i];
 84                     Q.push(next[now][i]);
 85                 }
 86         }
 87     }
 88     int cmp(char str1[],char str2[])
 89     {
 90         if(strlen(str1) < strlen(str2))
 91         {
 92             return 1;
 93         }else if(strlen(str1) > strlen(str2)){
 94             return 0 ;
 95         }else{
 96             if(strcmp(str1,str2) < 0)
 97                 return 1;
 98         }
 99         return 0;
100     }
101     int dp[100][maxn];
102     void solve()
103     {
104         memset(dp,-1,sizeof(dp));
105         dp[0][0] = 0 ;
106         int ai = 0 ;
107         int aj = 0 ;
108         int mx = 0;
109         char tmp[55];
110         char ans[55];
111         strcpy(ans,"");
112         strcpy(str[0][0],"");
113         for(int i = 0 ;i < n;i ++)
114         {
115             for(int j =0 ;j < L ;j ++)
116             {
117                 if(dp[i][j] != -1 )
118                 {
119                     strcpy(tmp,str[i][j]);
120                     int len = strlen(str[i][j]);
121
122                     for(int s = 0 ;s < 26 ;s ++)
123                     {
124                         int nex = next[j][s];
125                         tmp[len] = ‘a‘ + s;
126                         tmp[len + 1] = 0;
127                         int tt = dp[i][j];
128
129                         if(end[nex] != -1)
130                             tt += end[nex];
131
132                         if(tt > dp[i+1][nex] ||(tt == dp[i+1][nex] && cmp(tmp,str[i+1][nex]) ))
133                         {
134                             dp[i+1][nex] = tt;
135                             strcpy(str[i+1][nex],tmp);
136                             if(tt > mx ||(tt == mx && cmp(tmp,ans)))
137                             {
138                                 mx = tt;
139                                 strcpy(ans,tmp);
140                                 //printf("%s %d\n",ans,mx);
141                             }
142                         }
143                     }
144                 }
145             }
146         }
147         printf("%s\n",ans);
148     }
149
150 };
151
152 Trie ac;
153 char tstr[205][20];
154 int main(){
155     int t;
156     scanf("%d",&t);
157     while(t--)
158     {
159         scanf("%d %d",&n,&m);
160         ac.init();
161         for(int i = 1;i <= m ;i ++ )
162         {
163             scanf("%s",tstr[i]);
164         }
165         int temp ;
166         for(int i = 1; i <= m;i ++)
167         {
168             scanf("%d",&temp);
169             ac.insert(tstr[i],temp) ;
170         }
171         ac.build();
172         ac.solve();
173     }
174     return 0;
175 }

时间: 2024-10-25 13:08:11

HDU 2296 Ring AC自动机 + DP的相关文章

HDU 2296 Ring [AC自动机 DP 打印方案]

Ring Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3536 Accepted Submission(s): 1153 Problem Description For the hope of a forever love, Steven is planning to send a ring to Jane with a romantic

[hdu2296]Ring(AC自动机+dp)

题意:你M个单词构成一个词典,每个单词有一个权值(单词出现多次算多个权值),现在要你构造一个不超过长度N的字符串,使得该字符串权值最大.如果出现多个答案,输出最短的,如果依然有多解,输出字典序最小的. 解题关键:最典型的AC自动机上跑dp. 令$dp[i][j] = x$表示走了i步到达j点的最大价值,则 转移方程:$dp[i][j] = \max (dp[i][j],dp[i-1][k] + val[j])$ $val[i]$代表以某前缀的价值总和. 注意这里是多对多的关系,需用从遍历起点时更

hdu 2296 aC自动机+dp(得到价值最大的字符串)

Ring Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3180    Accepted Submission(s): 1033 Problem Description For the hope of a forever love, Steven is planning to send a ring to Jane with a rom

hdu 2457 AC自动机+dp

DNA repair Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2004    Accepted Submission(s): 1085 Problem Description Biologists finally invent techniques of repairing DNA that contains segments c

HDU 3341 Lost&#39;s revenge AC自动机+dp

Lost's revenge Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Submission(s): 3757    Accepted Submission(s): 1020 Problem Description Lost and AekdyCoin are friends. They always play "number game"(A bor

Hdu 3341 Lost&#39;s revenge (ac自动机+dp+hash)

题目大意: 给出很多个DNA串,每一个串的价值为1,最后给出一个长串,要你重新排列最后的串使之它所有的子串的权值和最大. 思路分析: 最先容易想到的思路就是搜!管她3721..直接一个字符一个字符的码,然后在AC自动机上判断最后的权值.TLE哟. 然后发现搜过不去,那就dp咯.再容易想到的就是dp[i][a][b][c][d] 表示此时遍历AC自动机的节点在i,然后构成了a个A,b个G,c个C,d个T的权值. 再一看内存,500*40*40*40*40...然后...就没有然后了 再想,因为它说

hdu 2825 Wireless Password(ac自动机&amp;dp)

Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4022    Accepted Submission(s): 1196 Problem Description Liyuan lives in a old apartment. One day, he suddenly found that there

hdu 4878 ZCC loves words(AC自动机+dp+矩阵快速幂+中国剩余定理)

hdu 4878 ZCC loves words(AC自动机+dp+矩阵快速幂+中国剩余定理) 题意:给出若干个模式串,总长度不超过40,对于某一个字符串,它有一个价值,对于这个价值的计算方法是这样的,设初始价值为V=1,假如这个串能匹配第k个模式串,则V=V*prime[k]*(i+len[k]),其中prime[k]表示第k个素数,i表示匹配的结束位置,len[k]表示第k个模式串的长度(注意,一个字符串可以多次匹配同意个模式串).问字符集为'A'-'Z'的字符,组成的所有的长为L的字符串,

HDU 2243 考研路茫茫――单词情结 (AC自动机 + dp)

HDU 2243 考研路茫茫――单词情结 题意:给定一些词根,如果一个单词包含有词根,则认为是有效的.现在问长度不超过L的单词里面,有多少有效的单词? 思路:这道题和POJ 2778是同样的思路.POJ 2778是要找出长度为L的单词里面有多少无效的单词.那么根据同样的方法构造矩阵,然后所有无效的单词个数为 A + A^2 + ... + A^l 个.而所有单词的个数为26 + 26^2 + - + 26^l 个.两个减一下即为答案. 矩阵连乘求和:I + A^2 + A^3 + ... + A