hdu4758(AC自动机+状态压缩dp)

链接:点击打开链接

题意:在一个矩阵内从左上角走到右下角,向右走得到一个R向下走得到一个D,问最后有几种走到右下角时得到的字符串包含题中给出的两个字符串

代码:

#include <queue>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int MOD=1000000007;
int q[205],dp[105][105][205][4];
int fail[205],vis[205],val[205];
int str[205][30],dis[205];
int root,id;
int change(char c){
    if(c=='D')return 1;
    return 0;
}                                               //只有两个字符
void insert(char *s){
    int u=0;
    for(;*s;s++){
        if(!str[u][change(*s)])
        str[u][change(*s)]=root++;
        u=str[u][change(*s)];
    }
    dis[u]|=(1<<(id-1));
    id++;
}
void getfail(){
    int u,v,i,l,r,temp;
    l=0,r=0;
    q[r++]=0;
    while(l<r){
       u=q[l++];
       for(i=0;i<2;i++){
            if(!str[u][i])
            str[u][i]=str[fail[u]][i];
            else
            {
                temp=str[u][i];
                if(u)
                fail[temp]=str[fail[u]][i];
                dis[temp]|=dis[fail[temp]];
                q[r++]=temp;
            }
        }
    }
}
int main(){
    int n,m,i,j,t,x,y,z,ans,p,q,k,h;
    char s[1005];
    scanf("%d",&t);
    while(t--){
    scanf("%d%d",&m,&n);
    root=id=1;
    memset(str,0,sizeof(str));
    memset(val,0,sizeof(val));
    memset(dis,0,sizeof(dis));
    memset(fail,0,sizeof(fail));
    for(i=0;i<2;i++){
        scanf("%s",s);
        insert(s);
    }
    getfail();
    memset(dp,0,sizeof(dp));
    dp[0][0][0][0]=1;                           
    for(i=0;i<=n;i++)
    for(j=0;j<=m;j++)                           //在ij点状态是h的数量
    for(k=0;k<root;k++)
    for(h=0;h<4;h++)
    if(dp[i][j][k][h]){
        if(i<n)
        dp[i+1][j][str[k][1]][h|dis[str[k][1]]]+=dp[i][j][k][h];
        dp[i+1][j][str[k][1]][h|dis[str[k][1]]]%=MOD;
        if(j<m)
        dp[i][j+1][str[k][0]][h|dis[str[k][0]]]+=dp[i][j][k][h];
        dp[i][j+1][str[k][0]][h|dis[str[k][0]]]%=MOD;
    }
    ans=0;                                      //这类题还是很相似的
    for(j=0;j<root;j++)
    ans=(ans+dp[n][m][j][3])%MOD;
    printf("%d\n",ans);
    }
    return 0;
}


 

你可能感兴趣的:(源码,动态规划,ACM,poj)