HNU 13108 Just Another Knapsack Problem DP + Trie树优化

题意:

  给你一个文本串,和一些模式串,每个模式串都有一个价值,让你选一些模式串来组成文本串,使获得的价值最大。每个模式串不止能用一次。

思路:

  多重背包,枚举文本串的每个位置和模式串,把该模式串拼接在当前位置,看下一个位置是否能得到更优值。但是,存在很多模式串不能拼在当前位置的,无效状态。所以可以用Trie树来优化转移。

代码:

  

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <string>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <functional>
#include <cctype>
#include <time.h>

using namespace std;

const int INF = 1<<30;
const int MAXN = 1e5+5;
const int MAXLEN = 333;
const int MAXNODE = 1e5+5;;

struct Trie {
    int ch[MAXNODE][26];
    int val[MAXNODE], use;

    inline void init() {
        for (int i = 0; i < 26; i++) ch[0][i] = 0;
        val[0] = 0;
        use = 1;
    }
    inline int New() {
        for (int i = 0; i < 26; i++) ch[use][i] = 0;
        val[use] = 0;
        return use++;
    }
    inline int idx(char c) {
        return c - 'a';
    }
    void insert(char str[], int v) {
        int len = strlen(str);
        int p = 0;
        for (int i = 0; i < len; i++) {
            int c = idx(str[i]);
            if (!ch[p][c]) ch[p][c] = New();
            p = ch[p][c];
        }
        val[p] = max(val[p], v);
    }
    int solve(char S[], int dp[]) {
        int len = strlen(S);
        for (int i = 0; i <= len; i++) dp[i] = -1;
        dp[0] = 0;
        for (int i = 0; i < len; i++) {
            if (dp[i]<0) continue;
            for (int j = i, p = 0; j <= len; j++) {
                int c = idx(S[j]);
                if (val[p]) dp[j] = max(dp[j], dp[i]+val[p]);
                p = ch[p][c];
                if (p==0) break;
            }
        }
        return max(dp[len], 0);
    }
};

Trie solver;

char S[MAXN], P[MAXLEN];
int dp[MAXN];
int m, v;

int main() {
    #ifdef Phantom01
        freopen("HNU13108.txt", "r", stdin);
    #endif //Phantom01

    while (scanf("%s", S)!=EOF) {
        scanf("%d", &m);
        solver.init();
        for (int i = 0; i < m; i++) {
            scanf("%s%d", P, &v);
            solver.insert(P, v);
        }
        printf("%d\n", solver.solve(S, dp));
    }

    return 0;
}
View Code

 

posted @ 2014-12-01 17:43  Phantom01  阅读(221)  评论(0编辑  收藏  举报