首页 > 代码库 > hdu 4758 Walk Through Squares(AC自动机+状态压缩DP)

hdu 4758 Walk Through Squares(AC自动机+状态压缩DP)

题目链接:hdu 4758 Walk Through Squares

题意:

给你一个n*m的网格,现在你要从(1,1)走到(n,m),每次只能向右走或者向下走,走完后会形成一个包含R,D的序列,这个序列必须要包含题目给出的两个字符串,问有多少种方案。

题解:

由于要从(1,1)走到(n,m),所以这个形成的字符串包含R和D的数量是一定的。

现在考虑dp[u][i][j][k],表示包含两种串的组合状态,走了i个D,走了j个R,走到了k这个AC自动机的节点的方案数,然后dp一下就行了。复杂度为O(3*n*m*len(s1)*len(s2))

技术分享
 1 #include<bits/stdc++.h>
 2 #define mst(a,b) memset(a,b,sizeof(a))
 3 #define F(i,a,b) for(int i=(a);i<=(b);++i)
 4 using namespace std;
 5 
 6 const int AC_N=300+7,tyn=2;
 7 int t,n,m,dp[4][111][111][212],P=1e9+7,ans;
 8 char a[101],b[101];
 9 inline void up(int &a,int b){a=(a+b)%P;}
10 
11 struct AC_automation{
12     int tr[AC_N][tyn],cnt[AC_N],Q[AC_N],fail[AC_N],tot;
13     inline int getid(char x){
14         if(x==D)return 0;
15         return 1;
16     }
17     void nw(){cnt[++tot]=0,fail[tot]=0;mst(tr[tot],0);}
18     void init(){tot=-1,fail[0]=-1,nw();}
19     void insert(char *s,int idx,int x=0){
20         for(int len=strlen(s),i=0,w;i<len;x=tr[x][w],i++)
21             if(!tr[x][w=getid(s[i])])nw(),tr[x][w]=tot;
22         cnt[x]=1<<idx;
23     }
24     void build(int head=1,int tail=0){
25         for(int i=0;i<tyn;i++)if(tr[0][i])Q[++tail]=tr[0][i];
26         while(head<=tail)for(int x=Q[head++],i=0;i<tyn;i++)
27             if(tr[x][i])
28             {
29                 fail[tr[x][i]]=tr[fail[x]][i],Q[++tail]=tr[x][i];
30                 cnt[tr[x][i]]|=cnt[tr[fail[x]][i]];
31             }
32             else tr[x][i]=tr[fail[x]][i];
33     }
34     void solve()
35     {
36         mst(dp,0),dp[0][0][0][0]=1;
37         F(u,0,3)F(i,0,n)F(j,0,m)F(k,0,tot)
38         {
39             if(!dp[u][i][j][k])continue;
40             up(dp[u|cnt[tr[k][0]]][i+1][j][tr[k][0]],dp[u][i][j][k]);
41             up(dp[u|cnt[tr[k][1]]][i][j+1][tr[k][1]],dp[u][i][j][k]);
42         }
43         ans=0;
44         F(k,0,tot)up(ans,dp[3][n][m][k]);
45         printf("%d\n",ans);
46     }
47 }AC;
48 
49 
50 int main()
51 {
52     scanf("%d",&t);
53     while(t--)
54     {
55         scanf("%d%d%s%s",&m,&n,a,b);
56         AC.init(),AC.insert(a,0),AC.insert(b,1);
57         AC.build(),AC.solve();
58     }
59     return 0;
60 }
View Code

 

hdu 4758 Walk Through Squares(AC自动机+状态压缩DP)