码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2020-02-20 23:45:24      阅读:84      评论:0      收藏:0      [点我收藏+]

标签:eof   else   get   push   +=   set   动态规划   int   cout   

传送门

默认大家都学过trie与AC自动机。

先求出fail,对于每个节点维护一个sum,sum[u]待表从根到u所形成的字符串能拿到几分。显然sum[u]=sum[fail] + (u是几个字符串的结尾)。

设dp[i][j]代表长度为i到trie树上的j号节点所得的最大分数,显然有dp[i+1][j的字符k儿子] = max{dp[i+1][j的字符k儿子], dp[i][j] + sum[j的字符k儿子]}

memset(dp, -1, sizeof(dp));
dp[0][1] = 0;
for (int i = 1; i <= k; i++) {
    for (int j = 1; j <= tot; j++) {
        if (dp[i - 1][j] == -1) continue;
        for (int l = 0; l < 26; l++) {
            dp[i][trie[j][l]] = max(dp[i][trie[j][l]], dp[i - 1][j] + sum[trie[j][l]]);
        }
    }
}

然后答案就是max{dp[k][i]},i是所有trie树上的节点。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int n, k;
char s[1000];
int tu[1000][26];
int trie[1000][26], tot = 1;
int fail[1000], sum[1000];
int dp[1010][1000];
queue<int> q;
int main() {
    scanf("%d%d", &n, &k);
    for (int i = 1, len; i <= n; i++) {
        scanf("%s", s + 1);
        len = strlen(s + 1);
        int p = 1;
        for (int j = 1; j <= len; j++) {
            int m = s[j] - A;
            if (!trie[p][m]) trie[p][m] = ++tot;
            p = trie[p][m];
        }
        sum[p]++;
    }
    for (int i = 0; i < 26; i++) trie[0][i] = 1;
    fail[1] = 0;
    q.push(1);
    while (!q.empty()) {
        int p = q.front(); q.pop();
        for (int i = 0; i < 26; i++) {
            if (trie[p][i]) {
                fail[trie[p][i]] = trie[fail[p]][i];
                sum[trie[p][i]] += sum[fail[trie[p][i]]];
                q.push(trie[p][i]);
            } else {
                trie[p][i] = trie[fail[p]][i];
            }
        }
    }
    memset(dp, -1, sizeof(dp));
    dp[0][1] = 0;
    for (int i = 1; i <= k; i++) {
        for (int j = 1; j <= tot; j++) {
            if (dp[i - 1][j] == -1) continue;
            for (int l = 0; l < 26; l++) {
                dp[i][trie[j][l]] = max(dp[i][trie[j][l]], dp[i - 1][j] + sum[trie[j][l]]);
            }
        }
    }
    int ans = -1;
    for (int i = 1; i <= tot; i++) {
        ans = max(ans, dp[k][i]);
    }
    cout << ans;
    return 0;
}

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

标签:eof   else   get   push   +=   set   动态规划   int   cout   

原文地址:https://www.cnblogs.com/zcr-blog/p/12339695.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!