• HDU-2296-Ring(AC自动机, DP)


    链接:

    https://vjudge.net/problem/HDU-2296

    题意:

    For the hope of a forever love, Steven is planning to send a ring to Jane with a romantic string engraved on. The string's length should not exceed N. The careful Steven knows Jane so deeply that he knows her favorite words, such as "love", "forever". Also, he knows the value of each word. The higher value a word has the more joy Jane will get when see it.
    The weight of a word is defined as its appeared times in the romantic string multiply by its value, while the weight of the romantic string is defined as the sum of all words' weight. You should output the string making its weight maximal.

    思路:

    建trie图, DP[i][j]表示走i步到j点的最大值, 往下更新, 累计值,同时记录路径, 比较路径大小.

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    //#include <memory.h>
    #include <queue>
    #include <set>
    #include <map>
    #include <algorithm>
    #include <math.h>
    #include <stack>
    #include <string>
    #include <assert.h>
    #include <iomanip>
    #include <iostream>
    #include <sstream>
    #define MINF 0x3f3f3f3f
    using namespace std;
    typedef long long LL;
    const LL MOD = 20090717;
    const LL MAXN = 110;
    const int MAXASCII = 26;
    
    struct TrieTree
    {
        int Next[MAXASCII];
        int end;
        int fail;
        void Clear()
        {
            memset(Next, 0, sizeof(Next));
            end = 0;
        }
    }tree[10000];
    
    char s[MAXN][55];
    int Val[MAXN];
    int Dp[55][1111];
    char Path[55][1111][55];
    int n, m, k, cnt;
    
    void Insert(char *s, int x)
    {
        int len = strlen(s);
        int p = 0;
        for (int i = 0;i < len;i++)
        {
            if (tree[p].Next[s[i]-'a'] == 0)
                tree[p].Next[s[i]-'a'] = ++cnt, tree[cnt].Clear();
            p = tree[p].Next[s[i]-'a'];
        }
        tree[p].end += x;
    }
    
    void BuildAC()
    {
        queue<int> que;
        for (int i = 0;i < MAXASCII;i++)
        {
            if (tree[0].Next[i] != 0)
            {
                tree[tree[0].Next[i]].fail = 0;
                que.push(tree[0].Next[i]);
            }
        }
        while (!que.empty())
        {
            int u = que.front();
            que.pop();
            tree[u].end += tree[tree[u].fail].end;
            for (int i = 0;i < MAXASCII;i++)
            {
                if (tree[u].Next[i] != 0)
                {
                    tree[tree[u].Next[i]].fail = tree[tree[u].fail].Next[i];
                    que.push(tree[u].Next[i]);
                }
                else
                    tree[u].Next[i] = tree[tree[u].fail].Next[i];
            }
        }
    }
    
    void Solve()
    {
        memset(Dp, -1, sizeof(Dp));
        memset(Path, 0, sizeof(Path));
        Dp[0][0] = 0;
        int maxlen = 0;
        for (int i = 0;i <= n;i++)
        {
            for (int j = 0;j <= cnt;j++)
            {
                if (Dp[i][j] == -1)
                    continue;
                for (int t = 0;t < 26;t++)
                {
                    int node = tree[j].Next[t];
                    if (Dp[i+1][node] < Dp[i][j]+tree[node].end)
                    {
                        Dp[i+1][node] = Dp[i][j]+tree[node].end;
                        strcpy(Path[i+1][node], Path[i][j]);
                        Path[i+1][node][i] = (char)(t+'a');
                    }
                    else if (Dp[i+1][node] == Dp[i][j]+tree[node].end)
                    {
                        char tmp[55] = {0};
                        strcpy(tmp, Path[i][j]);
                        tmp[i] = (char)(t+'a');
                        if (strcmp(tmp, Path[i+1][node]) < 0)
                            strcpy(Path[i+1][node], tmp);
                    }
                }
            }
        }
        int p1 = 0, p2 = 0;
        for (int i = 1;i <= n;i++)
        {
            for (int j = 0;j <= cnt;j++)
            {
                if (Dp[i][j] > Dp[p1][p2])
                    p1 = i, p2 = j;
                else if (Dp[i][j] == Dp[p1][p2] && p1 == i && strcmp(Path[p1][p2], Path[i][j]) > 0)
                    p1 = i, p2 = j;
            }
        }
        puts(Path[p1][p2]);
    }
    
    int main()
    {
        int t;
        scanf("%d", &t);
        while (t--)
        {
            cnt = 0;
            tree[cnt].Clear();
            scanf("%d%d", &n, &m);
            for (int i = 1;i <= m;i++)
            {
                scanf("%s", s[i]);
            }
            for (int i = 1;i <= m;i++)
            {
                scanf("%d", &Val[i]);
                Insert(s[i], Val[i]);
            }
            BuildAC();
            Solve();
        }
    
        return 0;
    }
    
  • 相关阅读:
    openjudge666:放苹果—题解
    欢迎来到路由器的世界!这里是开端
    Codevs1169:传纸条——题解
    POJ3498:March of the Penguins——题解
    模板:并查集
    模板:快速幂
    模板:排序(三)
    程序员之间的鄙视链
    自动化测试的成本高效果差,那么自动化测试的意义在哪呢
    自动化测试的成本高效果差,那么自动化测试的意义在哪呢
  • 原文地址:https://www.cnblogs.com/YDDDD/p/11641514.html
Copyright © 2020-2023  润新知