zoukankan      html  css  js  c++  java
  • HDU-3341-Lost's revenge(AC自动机, DP, 压缩)

    链接:

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

    题意:

    Lost and AekdyCoin are friends. They always play "number game"(A boring game based on number theory) together. We all know that AekdyCoin is the man called "nuclear weapon of FZU,descendant of Jingrun", because of his talent in the field of number theory. So Lost had never won the game. He was so ashamed and angry, but he didn't know how to improve his level of number theory.

    One noon, when Lost was lying on the bed, the Spring Brother poster on the wall(Lost is a believer of Spring Brother) said hello to him! Spring Brother said, "I'm Spring Brother, and I saw AekdyCoin shames you again and again. I can't bear my believers were being bullied. Now, I give you a chance to rearrange your gene sequences to defeat AekdyCoin!".

    It's soooo crazy and unbelievable to rearrange the gene sequences, but Lost has no choice. He knows some genes called "number theory gene" will affect one "level of number theory". And two of the same kind of gene in different position in the gene sequences will affect two "level of number theory", even though they overlap each other. There is nothing but revenge in his mind. So he needs you help to calculate the most "level of number theory" after rearrangement.

    思路:

    看得出DP, 但是不会记录状态.
    考虑a,t,g,c的个数, 令每个的进制为个数加1.则0-x, 用x+1进制存储.
    枚举使用状态..
    会存在重复

    代码:

    #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 = 2e6+10;
    const int MAXASCII = 4;
    
    struct TrieTree
    {
        int Next[MAXASCII];
        int end;
        int fail;
        void Clear()
        {
            memset(Next, 0, sizeof(Next));
            end = 0;
            fail = 0;
        }
    }tree[MAXN];
    
    char s[MAXN];
    int Dp[1010][11*11*11*11+10];
    map<char, int> Mp;
    int n, m, k, cnt;
    
    void Insert(char *s)
    {
        int len = strlen(s);
        int p = 0;
        for (int i = 0;i < len;i++)
        {
            if (tree[p].Next[Mp[s[i]]] == 0)
                tree[p].Next[Mp[s[i]]] = ++cnt, tree[cnt].Clear();
            p = tree[p].Next[Mp[s[i]]];
        }
        tree[p].end++;
    }
    
    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];
            }
        }
    }
    
    int Solve()
    {
        int Num[4] = {0}, Bit[4];
        int len = strlen(s+1);
        for (int i = 1;i <= len;i++)
            Num[Mp[s[i]]]++;
        Bit[0] = (Num[3]+1)*(Num[2]+1)*(Num[1]+1);
        Bit[1] = (Num[3]+1)*(Num[2]+1);
        Bit[2] = (Num[3]+1);
        Bit[3] = 1;
        memset(Dp, -1, sizeof(Dp));
        Dp[0][0] = 0;
        for (int A = 0;A <= Num[0];A++)
        {
            for (int B = 0; B <= Num[1]; B++)
                for (int C = 0; C <= Num[2]; C++)
                    for (int D = 0; D <= Num[3]; D++)
                    {
                        int state = A*Bit[0]+B*Bit[1]+C*Bit[2]+D;
                        for (int j = 0;j <= cnt;j++)
                        {
                            if (Dp[j][state] == -1)
                                continue;
                            for (int t = 0;t < 4;t++)
                            {
                                if (t == 0 && A == Num[0])
                                    continue;
                                if (t == 1 && B == Num[1])
                                    continue;
                                if (t == 2 && C == Num[2])
                                    continue;
                                if (t == 3 && D == Num[3])
                                    continue;
                                int node = tree[j].Next[t];
                                Dp[node][state+Bit[t]] = max(Dp[node][state+Bit[t]], Dp[j][state]+tree[node].end);
                            }
                        }
                    }
        }
        int res = 0;
        int sta = Num[0]*Bit[0]+Num[1]*Bit[1]+Num[2]*Bit[2]+Num[3]*Bit[3];
        for (int i = 0;i <= cnt;i++)
            res = max(res, Dp[i][sta]);
        return res;
    }
    
    int main()
    {
        Mp['A'] = 0;
        Mp['T'] = 1;
        Mp['G'] = 2;
        Mp['C'] = 3;
        int testcnt = 0;
        while (~scanf("%d", &n) && n)
        {
            cnt = 0;
            tree[cnt].Clear();
            for (int i = 1;i <= n;i++)
            {
                scanf("%s", s);
                Insert(s);
            }
            scanf("%s", s+1);
            BuildAC();
            printf("Case %d: %d
    ", ++testcnt, Solve());
        }
    
        return 0;
    }
    
  • 相关阅读:
    管道命令'|' 和xargs find命令找到后把所有找到的删除
    UVa
    【手势交互】9. PS Move
    jquery时间格式化插件
    Android学习路线(十三)Activity生命周期——暂停和恢复(Pausing and Resuming )一个Activity
    hdu 2604 Queuing (矩阵高速幂)
    【Linux驱动】TQ2440 DM9000E网卡驱动移植(Linux-2.6.30.4)
    bzoj2648 SJY摆棋子
    Hive编程指南_学习笔记01
    通信协议中的转义符
  • 原文地址:https://www.cnblogs.com/YDDDD/p/11651590.html
Copyright © 2011-2022 走看看