hdu 4758 Walk Through Squares AC自动机

来源:互联网 发布:淘宝 企业店铺 假货 编辑:程序博客网 时间:2024/04/30 04:37

题意:

在一个(n+1)*(m+1)的矩阵中从0点到(n+1)(m+1)点,每次只能向左走或者向下走,问所有走法中包含所给出的2种子串的走法有多少种。

分析:

     AC自动机类的题目做多了,就能看出这类题的套路。可以根据这2个子串建立tire图然后记dp【x】【y】【t】【k】表示向左走x步右走y步到达自动机t节点时候为状态k(0<=k<4)(0-->不包含任何子串,1-->只包含第一种子串,2-->只包含第二种子串,3-->都包含)

ACcode:

#include <bits/stdc++.h>#define mod 1000000007using namespace std;int N,M,loop;char str[101];int dp[101][101][202][4];struct Aho{    struct state{        int next[2];        int fail,cnt;    }s[202];    queue<int>q;    int size;    void init(){        while(q.size())q.pop();        for(int i=0;i<202;++i){            memset(s[i].next,-1,sizeof(s[i].next));            s[i].fail=s[i].cnt=0;        }        size=1;    }    void  insert(char *str,int t){        int now=0;        int n=strlen(str);        for(int i=0;i<n;++i){            int id=0;            if(str[i]=='D')id=1;            if(s[now].next[id]==-1)            s[now].next[id]=size++;            now=s[now].next[id];        }        s[now].cnt|=t;    }    void build(){        s[0].fail=0;        for(int i=0;i<2;++i){            if(s[0].next[i]==-1)                s[0].next[i]=0;            else {                s[s[0].next[i]].fail=0;                q.push(s[0].next[i]);            }        }        while(q.size()){            int u=q.front();            q.pop();s[u].cnt|=s[s[u].fail].cnt;            for(int i=0;i<2;++i){                if(s[u].next[i]==-1)                    s[u].next[i]=s[s[u].fail].next[i];                else{                    s[s[u].next[i]].fail=s[s[u].fail].next[i];                    q.push(s[u].next[i]);                }            }        }        for(int i=0;i<=N;++i)            for(int j=0;j<=M;++j)                for(int t=0;t<=size;++t)                    for(int k=0;k<4;++k)                        dp[i][j][t][k]=0;        dp[0][0][0][0]=1;        for(int i=0;i<=N;++i)            for(int j=0;j<=M;++j)                for(int t=0;t<size;++t)                    for(int k=0;k<4;++k){                        if(dp[i][j][t][k]==0)continue;                        if(i<N)                            dp[i+1][j][s[t].next[0]][k|s[s[t].next[0]].cnt]=(dp[i+1][j][s[t].next[0]][k|s[s[t].next[0]].cnt]+dp[i][j][t][k])%mod;                        if(j<M)                            dp[i][j+1][s[t].next[1]][k|s[s[t].next[1]].cnt]=(dp[i][j+1][s[t].next[1]][k|s[s[t].next[1]].cnt]+dp[i][j][t][k])%mod;                    }        int ans=0;        for(int i=0;i<size;++i)            ans=(ans+dp[N][M][i][3])%mod;        printf("%d\n",ans);    }}aho;int main(){    scanf("%d",&loop);    while(loop--){        scanf("%d%d",&N,&M);        aho.init();        scanf("%s",str);        aho.insert(str,1);        scanf("%s",str);        aho.insert(str,2);        aho.build();    }    return 0;}/*103 3DDRRR4 4DDRRR5 5DDRRR6 6DDRRR*/


0 0
原创粉丝点击