hdu3341 AC自动机

来源:互联网 发布:mysql管理器 编辑:程序博客网 时间:2024/05/21 15:42

       这题没意思,卡时间卡的太紧了,主要就是知道这种类型的状态压缩怎么写就好了。

       假设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。

      

#include <iostream>#include <cstring>#include <cstdio>#include <queue>#define N 505#define Max 4using namespace std;int num[N],next[N][4],fail[N];int cnt,root;int newnode(){    fail[cnt] = 0;    num[cnt] = 0;    return cnt++;}int hash(char s){    if(s == 'A')return 0;    if(s == 'C')return 1;    if(s == 'G')return 2;    if(s == 'T')return 3;}void insert(char *str){    int i=0,s;    int t = root;    while(str[i])    {        s = hash(str[i]);        if(next[t][s]==0)            next[t][s]=newnode();        t = next[t][s];        i++;    }    num[t]++;}void build_ac_automation(){    queue<int>q;    int tmp = root;    q.push(tmp);    while(!q.empty())    {        tmp=q.front();        q.pop();        for(int i=0; i<Max; i++)            if(next[tmp][i]==NULL)            {                if(tmp==root)next[tmp][i] = root;                else next[tmp][i] = next[fail[tmp]][i];            }            else            {                if(tmp==root)fail[next[tmp][i]] = root;                else                {                    fail[next[tmp][i]] = next[fail[tmp]][i];                    num[next[tmp][i]]+=num[next[fail[tmp]][i]];                }                q.push(next[tmp][i]);            }    }}char s[50];int dp[505][11*11*11*11+5];int sum[4],bit[4];int main(){    int n,i,j,cas = 1;    while(scanf("%d",&n)&&n)    {        cnt = 0;        root = newnode();        memset(sum,0,sizeof(sum));        memset(dp,-1,sizeof(dp));        memset(next,0,sizeof(next));        for(i = 1;i<=n;i++)        {            scanf("%s",s);            insert(s);        }        build_ac_automation();        scanf("%s",s);        int l = strlen(s);        for(i = 0;i<l;i++)            sum[hash(s[i])]++;        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;        memset(dp,-1,sizeof(dp));        dp[root][0] = 0;        for(int A = 0;A <= sum[0];A++)            for(int B = 0;B <= sum[1];B++)                for(int C = 0;C <= sum[2];C++)                    for(int D = 0;D <= sum[3];D++)                    {                        int st = A*bit[0] + B*bit[1] + C*bit[2] + D*bit[3];                        for(int i = 0;i < cnt;i++)                            if(dp[i][st] >= 0)                            {                                for(int k = 0;k < 4;k++)                                {                                    if(k == 0 && A == sum[0])continue;                                    if(k == 1 && B == sum[1])continue;                                    if(k == 2 && C == sum[2])continue;                                    if(k == 3 && D == sum[3])continue;                                    dp[next[i][k]][st+bit[k]] = max(dp[next[i][k]][st+bit[k]],dp[i][st]+num[next[i][k]]);                                }                            }                    }        int ans = 0;        int status = sum[0]*bit[0] + sum[1]*bit[1] + sum[2]*bit[2] + sum[3]*bit[3];        for(int i = 0;i < cnt;i++)            ans = max(ans,dp[i][status]);        printf("Case %d: %d\n",cas++,ans);    }    return 0;}

原创粉丝点击