HDU 2457 ac机+DP(基础DP)

来源:互联网 发布:大数据时代 企业管理 编辑:程序博客网 时间:2024/05/19 07:10

http://acm.split.hdu.edu.cn/showproblem.php?pid=2457

大体思路就是说 :
对给定的字符串(病毒串)构造AC机,标记每个病毒串的末尾,并在构造fail指针时 如果当前节点的失败指针是病毒串那么当前节点也作为标记。 因为 AC机的状态转移会使得当前节点转移到失败指针所指向的节点中来。
之后把给你的串(匹配串)进行DP,假设DP初始值最大 MME(dp,inf) ,并设dp[0][0]=0;那么dp[i][j] 表示为 长为 i 的串如果走到了第 j 个状态那么有多少种方法。那么每次遇到病毒串要跳过,每个状态为INF时也要跳过,表明到达当前这个长度的第j个状态之前没有经历过 因为只有一个串,那么他所经过的状态一定是一样的。
之后到达 j 状态后枚举每个子节点,同样跳过所有病毒串,那么当增加了一个长度之后到达了另一个新状态后所得到的dp[i+1][当前j状态的某个儿子的状态] 就为 min(dp[i+1][[当前j状态的某个儿子的状态],dp[i][j](去掉当前节点之后判断当前节点是否需要改变,如果当前节点与你j状态此时的儿子一样不需要改变,如不一样则需要改变一次,那么dp[i][j]+1;

#include <stdio.h>#include <string.h>#include <iostream>#include <queue>#define maxs 1050#define MME(i,j) memset(i,j,sizeof(i))#define inf 0x3f3f3f3fusing namespace std;int id['Z'+1];char s[maxs];int dp[maxs][maxs];void setid(){    id['A']=0;    id['G']=1;    id['C']=2;    id['T']=3;}struct node{    int nexts[maxs][4],fail[maxs],ends[maxs];    int root,L;    int newnode()    {        for(int i=0;i<4;i++) nexts[L][i]=-1;        ends[L++]=0;        return L-1;    }    // Rt    void init() { L=0; root=newnode();MME(fail,0); MME(ends,0);}    void Insert(char *s)    {        int len=strlen(s),idex,now=root;        for(int i=0;i<len;i++)        {            idex=id[s[i]];            if(nexts[now][idex]==-1)                nexts[now][idex]=newnode();            now=nexts[now][idex];        }        ends[now]=1;// 标记该点为 疾病 DNA    }    void build()    {        queue<int>Q;        fail[root]=root;        for(int i=0;i<4;i++)        {            if(nexts[root][i]==-1)                nexts[root][i]=root;            else{                fail[nexts[root][i]]=root;                Q.push(nexts[root][i]);            }        }        int now;        while(!Q.empty())        {            now=Q.front();            if(ends[ fail[ now ] ])                ends[ now ]=1;            Q.pop();            for(int i=0;i<4;i++)            {                if( nexts[now][i]==-1 )                    nexts[now][i] = nexts[fail[now]][i];                else                {                    fail[ nexts[now][i] ] =nexts[fail[now]][i];                    Q.push(nexts[now][i]);                }            }        }    }    int DP(char *s)    {        MME(dp,inf);       // printf("%d\n",dp[1][1]);        dp[0][0]=0;        int len=strlen(s);        for( int i=0;i<len;i++ )        {            for( int j=0;j<L;j++ )            {                if( ends[j] )       continue;                if(dp[i][j]==inf ) continue;                for(int ch=0;ch<4;ch++)                {                    int &temp=nexts[j][ch];                    if( ends[temp] ) continue;                    dp[i+1][temp] = min(dp[i+1][temp],dp[i][j] + (id[s[i]]!=ch) );                }            }        }        int ans=inf;       for(int i=0; i<L; i++)       {           ans=min(ans,dp[len][i]);       }       return ans == inf?-1:ans;    }}AC;int main(){    int n,cas=1;    setid();    while(~scanf("%d",&n) && n)    {        AC.init();        for(int i=0;i<n;i++)        {            scanf("%s",s);            AC.Insert(s);        }        AC.build();       // puts("*/*/*/");        scanf("%s",s);      int   ans=AC.DP(s);    //puts("**************");        printf("Case %d: %d\n", cas ++, ans );    }    return 0;}
0 0
原创粉丝点击