EOJ-3261 字典树 + dp

来源:互联网 发布:新疆旅游知乎 编辑:程序博客网 时间:2024/05/29 14:06

题意:

题目链接:http://acm.ecnu.edu.cn/problem/3261/
给出一个词典,包括每个单词的频率,根据公式计算出单词的价值。现在给出一串字符串,要求将字符串分成若干单词,使得分割之后单词价值之后最大,并输出分割结果。


思路:

词典用字典树维护,对于每个字符串进行O(n^2)的dp,dp[j]=dp[i]+val[u],然后路径标记,输出结果即可。


代码:

#include <bits/stdc++.h>using namespace std;const int MAXN = 5005;const int MAXNODE = 3e5 + 10;const int SIGMA_SIZE = 30;struct Trie {    int ch[MAXNODE][SIGMA_SIZE];    double val[MAXNODE];    int sz;    void init() {        sz = 1;        memset(ch, 0, sizeof(ch));    }    int idx(char c) {        return c - 'a';    }    void Insert(char *s, double v) {        int u = 0, n = strlen(s);        for (int i = 0; i < n; i++) {            int c = idx(s[i]);            if (!ch[u][c]) {                memset(ch[sz], 0, sizeof(ch[sz]));                val[sz] = 0;                ch[u][c] = sz++;            }            u = ch[u][c];        }        val[u] = v;    }} trie;char str[MAXN], ss[MAXN];int pa[MAXN];double dp[MAXN];void show(int x) {    if (x == 0) return;    show(pa[x]);    if (pa[x] != 0) printf(" ");    for (int i = pa[x] + 1; i <= x; i++)        printf("%c", str[i]);}int main() {    //freopen("in.txt", "r", stdin);    int n, m;    scanf("%d", &n);    trie.init();    for (int i = 1; i <= n; i++) {        double x;        scanf("%s%lf", str, &x);        int len = strlen(str);        for (int j = 0; j < len; j++)            str[j] = tolower(str[j]);        double v = log(x) * len * len;        trie.Insert(str, v);        //cout << str << "  " << v <<endl;    }    scanf("%d", &m);    while (m--) {        scanf("%s", str + 1);        int len = strlen(str +1);        for (int i = 1; i <= len; i++) {            ss[i] = tolower(str[i]);        }        memset(dp, 0, sizeof(dp));        memset(pa, 0, sizeof(pa));        for (int i = 0; i < len; i++) {            int u = 0, j = i + 1;            for (; j <= len; j++) {                int c = trie.idx(ss[j]);                u = trie.ch[u][c];                if (dp[j] < dp[i] + trie.val[u]) {                    pa[j] = i;                    dp[j] = dp[i] + trie.val[u];                }                if (u == 0) break;            }        }        printf("%.6f\n", dp[len]);        show(len);        puts("");    }    return 0;}
原创粉丝点击