码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 3341 Lost's revenge (AC自动机 + DP)

时间:2015-08-18 12:04:35      阅读:145      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:Lost‘s revenge


解析:n个模式串,一个目标串。问目标串通过任意次交换字符最多能包含的模式串个数。(允许重叠)

字符最长是40
只需要记录ACGT出现的次数。
如果使用5维数组,显然超内存了。
假设ACGT的总数分别为num[0],num[1],num[2],num[3]
那么对于ACGT的数量分别为ABCD的状态可以记录为:  (网上大神讲的,至今还没弄明白。。。求指教)
A*(num[1]+1)*(num[2]+1)*(num[3]+1) + B*(num[2]+1)*(num[3]+1)+ C*(num[3]+1) +D
这样的状态最大就是11*11*11*11
复杂度也可以承受了。
字符串可能有重复的,用int来记录数量



AC代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;

const int INF = 0x3f3f3f3f;
struct Trie{
    int next[510][4], fail[510], end[510];
    int root, L;
    int newnode(){
        for(int i=0; i<4; i++)  next[L][i] = -1;
        end[L++] = 0;
        return L-1;
    }
    void init(){
        L = 0;
        root = newnode();
    }
    int getch(char ch){
        if(ch == 'A') return 0;
        if(ch == 'C') return 1;
        if(ch == 'G') return 2;
        return 3;
    }
    void insert(char buf[]){
        int len = strlen(buf);
        int now = root;
        for(int i=0; i<len; i++){
            if(next[now][getch(buf[i])] == -1)
                next[now][getch(buf[i])] = newnode();
            now = next[now][getch(buf[i])];
        }
        end[now] ++;
    }
    void build(){
        queue<int> Q;
        fail[root] = root;
        for(int i=0; i<4; i++)
            if(next[root][i] == -1) next[root][i] = root;
            else{
                fail[ next[root][i] ] = root;
                Q.push(next[root][i]);
            }
        while(!Q.empty()){
            int now = Q.front();
            Q.pop();
            end[now] += end[ fail[now] ];       //!!!
            for(int i=0; i<4; 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]);
                }
        }
    }
    int dp[510][11*11*11*11+5];
    int bit[4];
    int num[4];
    int solve(char buf[]){
        int len = strlen(buf);
        memset(num, 0, sizeof(num));
        for(int i=0; i<len; i++)    num[ getch(buf[i]) ] ++;
        bit[0] = (num[1] + 1) * (num[2] + 1) * (num[3] + 1);
        bit[1] = (num[2] + 1) * (num[3] + 1);
        bit[2] = (num[3] + 1);
        bit[3] = 1;
        memset(dp, -1, sizeof(dp));
        dp[root][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 s = A*bit[0] + B*bit[1] + C*bit[2] + D*bit[3];
                        for(int i=0; i<L; i++)
                            if(dp[i][s] >= 0){
                                for(int k=0; k<4; k++){
                                    if(k == 0 && A == num[0]) continue;
                                    if(k == 1 && B == num[1]) continue;
                                    if(k == 2 && C == num[2]) continue;
                                    if(k == 3 && D == num[3]) continue;
                                    dp[ next[i][k] ][s+bit[k]] = max(dp[ next[i][k] ][s+bit[k]], dp[i][s] + end[ next[i][k] ]);
                                }
                            }
                    }
        int ans = 0;
        int status = num[0]*bit[0] + num[1]*bit[1] + num[2]*bit[2] + num[3]*bit[3];
        for(int i=0; i<L; i++)
            ans = max(ans, dp[i][status]);
        return ans;
    }
};

char buf[50];
Trie ac;

int main(){
    #ifdef sxk
        freopen("in.txt", "r", stdin);
    #endif // sxk
    int n;
    int kase = 0;
    while(scanf("%d", &n) == 1 && n){
        ac.init();
        for(int i=0; i<n; i++){
            scanf("%s", buf);
            ac.insert(buf);
        }
        ac.build();
        scanf("%s", buf);
        printf("Case %d: %d\n", ++kase, ac.solve(buf));
    }
    return 0;
}


版权声明:本文为sxk原创文章,转载请附加本文链接^_^

HDU 3341 Lost's revenge (AC自动机 + DP)

标签:

原文地址:http://blog.csdn.net/u013446688/article/details/47748197

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!