zoukankan      html  css  js  c++  java
  • Lost's revenge

    题目大意:先给你一些子串,然后给你一个母串,母串里面的字母可以任意调换位置,问最多这个母串经过一些位置变动最多能包含多少个子串。
     
    分析:可以比较明显的看出来的DP,先求出来ATGC分别有多少,然后再处理,不过有个比较麻烦的地方,因为ATGC的字母数最多是40,因为不知道那种字母所以是40*40*40*40,很明显这种复杂度太高,开始使用了一次打标,把每种状态都保存下来,并且保存它的下一个状态,不过很不幸这种方法TLE了,因为找他的下一个状态不是太容易,看了大神的题解后明白,其实可以使用4种不同的进制来做,进制数就是这个碱基数的总个数,这样复杂度很明显就降低了,而且状态再转移的时候也很容易。
     
    代码如下:
    ===================================================================================================================================
    #include<iostream>
    #include<algorithm>
    #include<stdio.h>
    #include<string.h>
    #include<queue>
    using namespace std;
    
    const int MAXN = 15007;
    const int MaxSon = 4;
    const int oo = 1e9;
    
    int Find(char ch)
    {
        if(ch == 'A')return 0;
        if(ch == 'T')return 1;
        if(ch == 'G')return 2;
    
        return 3;
    }
    struct Ac_Trie
    {
        int next[507][4];
        int Fail[507], End[507];
        int root, cnt;
    
        int newnode()
        {
            for(int i=0; i<MaxSon; i++)
                next[cnt][i] = -1;
            Fail[cnt] = End[cnt] = false;
    
            return cnt++;
        }
        void InIt()
        {
            cnt = 0;
            root = newnode();
        }
        void Insert(char s[])
        {
            int now = root;
    
            for(int i=0; s[i]; i++)
            {
                int k = Find(s[i]);
    
                if(next[now][k] == -1)
                    next[now][k] = newnode();
                now = next[now][k];
            }
    
            End[now] += 1 ;
        }
        void GetFail()
        {
            int now = root;
            queue<int> Q;
    
            for(int i=0; i<MaxSon; i++)
            {
                if(next[now][i] == -1)
                    next[now][i] = root;
                else
                {
                    Fail[next[now][i]] = root;
                    Q.push(next[now][i]);
                }
            }
    
            while(Q.size())
            {
                now = Q.front();
                Q.pop();
    
                for(int i=0; i<MaxSon; i++)
                {
                    if(next[now][i] == -1)
                        next[now][i] = next[Fail[now]][i];
                    else
                    {
                        Fail[next[now][i]] = next[Fail[now]][i];
                        Q.push(next[now][i]);
                    }
                }
    
                End[now] += End[Fail[now]];
            }
        }
    };
    struct ATGC
    {
        int sum[4], bit[4];
        int dp[507][MAXN];
        Ac_Trie ac;
    
        void GetSum(char s[])
        {
            memset(sum, 0, sizeof(sum));
            memset(bit, 0, sizeof(bit));
    
            for(int i=0; s[i]; i++)
            {
                int k = Find(s[i]);
                sum[k]++;
            }
        }
        void GetBit()
        {
            bit[0] = (sum[1]+1)*(sum[2]+1)*(sum[3]+1);
            bit[1] = (sum[2]+1)*(sum[3]+1);
            bit[2] = sum[3]+1;
            bit[3] = 1;
        }
        int GetDp()
        {
            memset(dp, -1, sizeof(dp));
            dp[0][0] = 0;
    
            int ans = 0;
    
            for(int A=0; A<=sum[0]; A++)
            for(int T=0; T<=sum[1]; T++)
            for(int G=0; G<=sum[2]; G++)
            for(int C=0; C<=sum[3]; C++)
            {
                int k = A*bit[0] + T*bit[1] + G*bit[2] + C*bit[3];
    
                for(int i=0; i<ac.cnt; i++)
                {
                    if(dp[i][k] == -1)continue;
    
                    for(int j=0; j<MaxSon; j++)
                    {
                        if(j == 0 && A==sum[0])continue;
                        if(j == 1 && T==sum[1])continue;
                        if(j == 2 && G==sum[2])continue;
                        if(j == 3 && C==sum[3])continue;
    
                        int next = ac.next[i][j];
                        int nextk = k + bit[j];
    
                        dp[next][nextk] = max(dp[next][nextk], dp[i][k]+ac.End[next]);
                        ans = max(ans, dp[next][nextk]);
                    }
                }
            }
    
            return ans;
        }
    };
    
    ATGC a;
    
    int main()
    {
        int i, N, t=1;
    
        while(scanf("%d", &N), N)
        {
            char s[107];
            a.ac.InIt();
    
            for(i=0; i<N; i++)
            {
                scanf("%s", s);
                a.ac.Insert(s);
            }
            a.ac.GetFail();
    
            scanf("%s", s);
    
            a.GetSum(s);
            a.GetBit();
    
            int ans = a.GetDp();
    
            printf("Case %d: %d
    ", t++, ans);
        }
    
        return 0;
    }
  • 相关阅读:
    一些开发海学网站过程中的Javascript
    准备学习 Windows Forms 2.0 Programming
    终于买了个Dell d400二手笔记本
    Asp.Net应用程序中为什么要MachineKey?如何生成MachineKey?
    今天装了苏州数字电视
    windows Forms 编程实战 源代码
    重新整理 .net core 实践篇——— filter[四十四]
    not noly go —— 运行轨迹[一]
    .NET CLR基本术语
    [转]SqlServer四个排名函数(row_number、rank、dense_rank和ntile)的比较
  • 原文地址:https://www.cnblogs.com/liuxin13/p/4772879.html
Copyright © 2011-2022 走看看