HDU 2296

来源:互联网 发布:软件时间限制工具 编辑:程序博客网 时间:2024/06/07 00:36

思路:

开个结构体,dp[i][j]记录从i号节点开始走j步能得到的最大的权值,以及走到最大权值的方案,还有答案,每次枚举能走到的所有点,更新答案,如果答案一样就选择字典序小的一个。也可以只记录走到该节点的父亲节点,这样每次答案一样时选字典小的就通过不断回退来确定。


#include <iostream>#include <cstdio>#include <map>#include <cstring>#include <string>#include <queue>#define M 110#define N 60using namespace std;int n, m, val[M];char pat[M][15];class DPNode{public:    int val;    string str;};DPNode dp[M*11][N];class Node{public:    int endCnt, next[30], fail, val;    Node() {}    void clr()    {        endCnt = 0;        memset(next, 0, sizeof next);        fail = 0;        val = -1;    }};Node node[M*11];class Trie{public:    int root, cnt;    int newNode()    {        node[++cnt].clr();        return cnt;    }    void init()    {        cnt = 0;        root = newNode();    }    void ins(char pat[], int len, int val)    {        int p = root;        for(int i = 0; i < len; i++)        {            int cur = pat[i]-'a';            if(!node[p].next[cur])                node[p].next[cur] = newNode();            p = node[p].next[cur];        }        node[p].endCnt++;        node[p].val = val;    }    void build()    {        queue<int> q;        q.push(root);        while(!q.empty())        {            int cur = q.front();            q.pop();            for(int i = 0; i < 26; i++)            {                int nxt = node[cur].next[i];                if(nxt)                {                    int p = node[cur].fail;                    for(; p && node[p].next[i] == 0; p = node[p].fail);                    p = p ? node[p].next[i] : root;                    node[nxt].fail = p;                    q.push(nxt);                }            }        }    }    int cmp(string a, string b)    {        for(int i = a.length()-1; i >= 0; i--)        {            if(a[i] != b[i]) return a[i] < b[i];        }        return 0;    }    void solve()    {        for(int i = 1; i <= cnt; i++)        {            for(int j = 0; j <= n; j++)            {                dp[i][j].val = 0;                dp[i][j].str = "";            }        }        for(int i = 1; i <= cnt; i++)        {            if(node[i].endCnt > 0)                dp[i][0].val = node[i].val;        }        for(int i = 1; i <= n; i++)        {            for(int j = 1; j <= cnt; j++)            {                for(int k = 0; k < 26; k++)                {                    int p;                    if(node[j].next[k])                    {                        p = node[j].next[k];                    }                    else                    {                        p = node[j].fail;                        for(; p && node[p].next[k] == 0; p = node[p].fail);                        p = p ? node[p].next[k] : root;                    }                    if(dp[p][i-1].val > dp[j][i].val)                    {                        dp[j][i].val = dp[p][i-1].val;                        dp[j][i].str = dp[p][i-1].str+(char)(k+'a');                    }                    else if(dp[p][i-1].val == dp[j][i].val)                    {                        string temp = dp[p][i-1].str+(char)(k+'a');                        if(dp[j][i].str == "" || cmp(temp, dp[j][i].str))                        {                            dp[j][i].str = temp;                        }                    }                }                if(node[j].endCnt > 0)                        dp[j][i].val += node[j].val;            }        }        int maxv = dp[root][n].val;        string ans = "";        for(int i = n; i >= 0; i--)        {            if(dp[root][i].val < maxv) break;            ans = dp[root][i].str;        }        int lenans = ans.length();        for(int i = 0; i < lenans/2; i++) swap(ans[i], ans[lenans-1-i]);        //cout << "val: " << dp[root][n].val << endl;;        cout << ans << endl;    }};Trie trie;int main(){//freopen("C:\\Users\\zfh\\Desktop\\in.txt", "r", stdin);    int t; scanf("%d", &t);    while(t--)    {        trie.init();        scanf("%d%d", &n, &m);        for(int i = 0; i < m; i++)        {            scanf(" %s", pat[i]);        }        for(int i = 0; i < m; i++)        {            scanf("%d", &val[i]);        }        for(int i = 0; i < m; i++)        {            trie.ins(pat[i], strlen(pat[i]), val[i]);        }        trie.build();        trie.solve();    }    return 0;}


0 0
原创粉丝点击