• HDU 4758 Walk Through Squares (2013南京网络赛1011题,AC自动机+DP)


    题意:给n*m的地图,在地图的点上走,(n+1)*(m+1)个点,两种操作:往下走D和往右走R。现在要从左上角走到右下角,给定两个操作串,问包含这两个串的走法总共有多少种。

    做法:用这两个串构建自动机,然后只要在自动机上走n+m+1步就好了。就像一个递推,dp[x][y][i][cur]表示在i状态到达x,y坐标时走过的串的状态为cur时的总方案数

    //#pragma comment(linker, "/STACK:102400000")
    #include<cstdlib>
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<list>
    #include<queue>
    #include<vector>
    #define tree int o,int l,int r
    #define lson o<<1,l,mid
    #define rson o<<1|1,mid+1,r
    #define lo o<<1
    #define ro o<<1|1
    #define ULL unsigned long long
    #define LL long long
    #define inf 0x7fffffff
    #define eps 1e-7
    #define N 105
    #define M 1000000007
    using namespace std;
    int m,n,T,t,x,y,u;
    char a[N],b[N];
    int ch[N*2][2],num;
    int v[N*2];
    int d[N][N][N*2][4];
    int f[N*2],last[N*2];
    int idx(char c)
    {
        if(c=='R')return 1;
        return 0;
    }
    void init()
    {
        num=1;
        memset(d,-1,sizeof(d));
        memset(ch,0,sizeof(ch));
        memset(v,0,sizeof(v));
        memset(last,0,sizeof(last));
    }
    void insert(char str[],int val)
    {
        int u=0;
        for(int i=0;str[i];i++)
        {
            int c=idx(str[i]);
            if(ch[u][c]==0)
            {
                ch[u][c]=num++;
            }
            u=ch[u][c];
        }
        v[u]|=(1<<val);
        last[u]=v[u];
    }
    void getac()
    {
        queue<int>q;
        f[0]=0;
        for(int c=0;c<2;c++)
        {
            int u=ch[0][c];
            if(u)
            {
                q.push(u);
                f[u]=0;
    //            last[u]=0;//WA,意义改变了!
            }
        }
        while(!q.empty())
        {
            int r=q.front();
            q.pop();
            for(int i=0;i<2;i++)
            {
                int u=ch[r][i];
                if(u)
                {
                    q.push(u);
                    int s=f[r];
                    f[u]=ch[s][i];
                    last[u]|=v[f[u]]?v[f[u]]:v[last[f[u]]];//表示到此出现的值
    
                }
                else
                ch[r][i]=ch[f[r]][i];
            }
        }
    }
    int dp(int x,int y,int u,int s)
    {
        if(x==n&&y==m)
        {
            return s==3;
        }
    
        int &ans=d[x][y][u][s];
        if(ans!=-1)return ans;
        ans=0;
        if(x<n)
        {
            int v=ch[u][0];
            int ss=s|last[v];
            ans+=dp(x+1,y,v,ss);
            ans%=M;
        }
        if(y<m)
        {
            int v=ch[u][1];
            int ss=s|last[v];
            ans+=dp(x,y+1,v,ss);
            ans%=M;
        }
        return ans;
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("ex.in","r",stdin);
    #endif
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&m,&n);
            scanf("%s",a);
            scanf("%s",b);
            init();
            insert(a,0);
            insert(b,1);
            getac();
            printf("%d
    ",dp(0,0,0,0));
        }
        return 0;
    }
  • 相关阅读:
    day74 作业
    day73 基表 表关联
    不知道第几次分享了
    day72 序列化家族
    day72 作业
    vscode
    vuex
    linux python3.7的安装和配置
    使用多线程分批发送短信代码,分割list
    docker 容器里使用crontab不生效
  • 原文地址:https://www.cnblogs.com/sbaof/p/3336624.html
Copyright © 2020-2023  润新知