• 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
    ",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
  • 相关阅读:
    tp5.1接入支付宝网站支付
    go类型转换
    mysql常见sql练习题
    php 获取当前时间的 前一小时、一天、一个月、一年
    php如何检测是否有环
    Go的切片:长度和容量
    go实现小项目
    知乎网页版不登录如何浏览内容
    图挂了
    centos搭建php环境
  • 原文地址:https://www.cnblogs.com/bin-gege/p/7255548.html
Copyright © 2020-2023  润新知