现在的位置: 首页 > 综合 > 正文

hdu 3341 AC自动机+五维dp

2013年09月06日 ⁄ 综合 ⁄ 共 1844字 ⁄ 字号 评论关闭

Lost's revenge

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

#define pb push_back
struct node {
    int son[4],fail;
    int cnt;
    node(){cnt=0,fail=0;memset(son,0,sizeof(son));}
};
vector<node> ac;
int dp[510][11*11*11*11];//题目没说各个字母的数目,只说了总数40,所以四个状态得这样放到一维里
int hash[128];

void init() {
    hash['A']=0;
    hash['T']=1;
    hash['C']=2;
    hash['G']=3;
}

void insert(const char *str) {
    int p=0,i=0,tmp;
    while(str[p]) {
        tmp=hash[str[p]];
        if(!ac[i].son[tmp]) {
            ac[i].son[tmp]=ac.size();
            ac.pb(node());
        }
        i=ac[i].son[tmp];
        ++p;
    }
    ++ac[i].cnt;
}

void getFail() {
    queue<int> qu;
    qu.push(0);
    while(!qu.empty()) {
        int cur=qu.front();qu.pop();
        for(int i=0;i<4;++i) {
            int p=ac[cur].fail,son=ac[cur].son[i];
            if(son) qu.push(son);
            if(cur) {
                if(son) ac[son].fail=ac[p].son[i],ac[son].cnt+=ac[ac[p].son[i]].cnt;
                else ac[cur].son[i]=ac[p].son[i];
            }
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    int n,cas=0;
    init();
    while(cin >> n,n) {
        ac.clear();
        ac.pb(node());
        char str[45];
        while(n--) {
            cin >> str;
            insert(str);
        }
        int na[4];//各个字母个数
        memset(na,0,sizeof(na));
        cin >> str;
        int len=0;
        for(int i=0;str[i];++i) {
            ++len;
            switch(str[i]) {
                case 'A':++na[0];break;
                case 'T':++na[1];break;
                case 'C':++na[2];break;
                case 'G':++na[3];
            }
        }
        getFail();
        memset(dp,-1,sizeof(dp));
        dp[0][0]=0;
        register int ii[5],p[5];
        p[3]=1;
        p[2]=na[3]+1;//注意这里要+1,字母的数目为0的情况也要计算
        p[1]=(na[2]+1)*(na[3]+1);
        p[0]=(na[1]+1)*p[1];
        int ans=0;
        int size=ac.size();
        for(ii[0]=0;ii[0]<=na[0];++ii[0]) {
            for(ii[1]=0;ii[1]<=na[1];++ii[1]) {
                for(ii[2]=0;ii[2]<=na[2];++ii[2]) {
                    for(ii[3]=0;ii[3]<=na[3];++ii[3]) {
                        for(ii[4]=0;ii[4]<size;++ii[4]) {
                            int pp=ii[0]*p[0]+ii[1]*p[1]+ii[2]*p[2]+ii[3];
                            if(dp[ii[4]][pp]==-1) continue;
                            for(int k=0;k<4;++k) {
                                int son=ac[ii[4]].son[k];
                                if(ii[k]==na[k]) continue;
                                int ppp=pp+p[k];
                                dp[son][ppp]=max(dp[son][ppp],dp[ii[4]][pp]+ac[son].cnt);
                                if(ii[0]+ii[1]+ii[2]+ii[3]+1==len)
                                    ans=max(ans,dp[son][ppp]);
                            }
                        }
                    }
                }
            }
        }
        cout << "Case " << ++cas << ": " << ans << endl;
    }
    return 0;
}

抱歉!评论已关闭.