P3041 [USACO12JAN]视频游戏的连击Video Game Combos

Posted mjtcn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3041 [USACO12JAN]视频游戏的连击Video Game Combos相关的知识,希望对你有一定的参考价值。

P3041 [USACO12JAN]视频游戏的连击Video Game Combos

https://www.luogu.org/problemnew/show/P3041

 

分析:

  AC自动机。

  建立AC自动机,然后dp[i][j]表示经过了i个字符,到达自动机上j这个位置,的得分。

  那么dp[i-1][j] + val[ch[j][k]] -> dp[i][ch[j][k]]。

  表示从j点,往前走一步,加上新加一个字符产生的贡献。

 

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 
 5 const int N = 550;
 6 int ch[N][3], fail[N], last[N], val[N], f[1010][N], q[N], L, R, Index = 1;
 7 char s[22];
 8 
 9 void Insert(char *s) {
10     int u = 0, len = strlen(s);
11     for (int i=0; i<len; ++i) {
12         int c = s[i] - A;
13         if (!ch[u][c]) ch[u][c] = ++Index;
14         u = ch[u][c];
15     }
16     val[u] ++;
17 }
18 void build() {
19     L = 1, R = 0; fail[0] = 0;
20     for (int c=0; c<3; ++c) {
21         int u = ch[0][c];
22         if (u) q[++R] = u, fail[u] = last[u] = 0;
23     }
24     while (L <= R) {
25         int u = q[L++];
26         for (int c=0; c<3; ++c) {
27             int v = ch[u][c];
28             if (!ch[u][c]) {
29                 ch[u][c] = ch[fail[u]][c];
30                 continue;
31             }
32             q[++R] = v;
33             int p = fail[u];
34             while (p && !ch[p][c]) p = fail[p];
35             fail[v] = ch[p][c];
36         }
37         val[u] += val[fail[u]];
38     }
39 }
40 
41 int main () {
42     
43     int n,m; cin >> n >> m;
44     for (int i=1; i<=n; ++i) {
45         scanf("%s",s);
46         Insert(s);
47     }
48     build();
49     memset(f, -0x3f, sizeof(f));
50     f[0][0] = 0;
51 
52     // f[i][j]表示用了i个字符,在自动机的j号位置,可以得多少分 
53     for (int i=1; i<=m; ++i) 
54         for (int j=0; j<=Index; ++j)
55             for (int k=0; k<3; ++k) 
56                 f[i][ch[j][k]] = max(f[i][ch[j][k]], f[i-1][j]+val[ch[j][k]]);
57                 // 从j这个位置,经过字符k到达的点的得分为 经过i-1个点到j的得分+经过i个点到ch[j][k]的得分 
58 
59     int Ans = 0;
60     for (int i=0; i<=Index; ++i) Ans = max(Ans, f[m][i]);
61     cout << Ans;
62         
63     return 0;
64 }

 

以上是关于P3041 [USACO12JAN]视频游戏的连击Video Game Combos的主要内容,如果未能解决你的问题,请参考以下文章

[USACO12JAN]视频游戏的连击Video Game Combos(AC自动机+DP)

视频游戏的连击 [USACO12JAN](AC自动机+动态规划)

洛谷 P3041 [USACO12JAN] Video Game Combos

bzoj 1594: [Usaco2008 Jan]猜数游戏——二分+线段树

DTOJ #4492. 「USACO 2018 Jan」MooTube

[BZOJ1594] [Usaco2008 Jan]猜数游戏(二分 + 并查集)