题意 : 给出一个 n 行、m 列的方格图,现从图左上角(0, 0) 到右下角的 (n, m)走出一个字符串(规定只能往下或者往右走),向右走代表' R ' 向下走则是代表 ' D ' 最后从左上角到右下角,不同的路线会走出不同的字符串,问你这些不同的字符串有多少个是包含了接下来给定的两个子串。

分析 : 简单想想不难发现最后肯定是走了 (n+1) 个 ' D ' 和 (m+1)个 ' R ' ,那么也就是说用 (n+1) 个 ' D ' 和 (m+1)个 ' R ' 构造出长度为 (n+m+2) 的字符串,且包含给定的两个子串的方案数有多少个( 跟 HDU 3341 类似 ),那么来看看关键点,即考虑 ' D '与' R '的数量、以及当前节点包含了多少个子串、当前停留在Trie上哪个节点,那么可以定义出DP[i][j][k][l]代表在有 i 个 ' D '(即向下走了 i 步)、j 个 ' R '(向右走 j 步)、停留在 k 这个节点、包含子串情况 l 时的最大方案数,则状态转移方程为

每个节点能向 ' D ' 和 ' R ' 转移,这里以向 ' D ' 转移为例

DP[i+1][j][k][l | Trie[k]['D'].id] += DP[i][j][k][l] ( Trie[k]['D']代表从 k 转移到状态为' D '节点,其 id 表示包含字母的情况 )

DP初始状态为 DP[0][0][0][0] = 1、DP其他 = 0

#include<bits/stdc++.h>
using namespace std;
;
;
;
int n, m;
][][][];
struct Aho{
    struct StateTable{
        int Next[Letter];
        int fail, id;
    }Node[Max_Tot];
    int Size;
    queue<int> que;

    inline void init(){
        while(!que.empty()) que.pop();
        memset(Node[].Next, , ].Next));
        Node[].fail = Node[].id = ;
        Size = ;
    }

    inline void insert(char *s, int id){
        ;
        ; s[i]; i++){
            int idx = (s[i] == 'D');
            if(!Node[now].Next[idx]){
                memset(Node[Size].Next, , sizeof(Node[Size].Next));
                Node[Size].fail = Node[Size].id = ;
                Node[now].Next[idx] = Size++;
            }
            now = Node[now].Next[idx];
        }
        Node[now].id |= (<<id);
    }

    inline void BuildFail(){
        Node[].fail = ;
        ; i<Letter; i++){
            ].Next[i]){
                Node[Node[].Next[i]].fail = ;
                que.push(Node[].Next[i]);
            }].Next[i] = ;
        }
        while(!que.empty()){
            int top = que.front(); que.pop();
            Node[top].id |= Node[Node[top].fail].id;
            ; i<Letter; i++){
                int &v = Node[top].Next[i];
                if(v){
                    que.push(v);
                    Node[v].fail = Node[Node[top].fail].Next[i];
                }else v = Node[Node[top].fail].Next[i];
            }
        }
    }
}ac;

int Solve()
{
    ; i<=n; i++)
        ; j<=m; j++)
            ; k<ac.Size; k++)
                ; l<; l++)
                    dp[i][j][k][l] = ;

    dp[][][][] = ;

    ; i<=n; i++){
        ; j<=m; j++){
            ; k<ac.Size; k++){
                ; l<; l++){
                    ){
                        ];
                        ];
                        dp[i][j+][Node1][l | ac.Node[Node1].id] += dp[i][j][k][l];
                        dp[i+][j][Node2][l | ac.Node[Node2].id] += dp[i][j][k][l];
                        dp[i][j+][Node1][l | ac.Node[Node1].id] %= MOD;
                        dp[i+][j][Node2][l | ac.Node[Node2].id] %= MOD;
                    }
                }
            }
        }
    }

    ;
    ; i<ac.Size; i++){
        ans += dp[n][m][i][];
        ans %= MOD;
    }
    return ans%MOD;
}
];
int main(void)
{
    int nCase;
    scanf("%d", &nCase);
    while(nCase--){
        scanf("%d %d", &m, &n);
        ac.init();
        ; i<; i++){
            scanf("%s", S);
            ac.insert(S, i);
        }ac.BuildFail();
        printf("%d\n", Solve());
    }
    ;
}

HDU 4758 Walk Through Squares ( Trie图 && 状压DP && 数量限制类型 )的更多相关文章

  1. HDU 3341 Lost's revenge ( Trie图 && 状压DP && 数量限制类型 )

    题意 : 给出 n 个模式串,最后给出一个主串,问你主串打乱重组的情况下,最多能够包含多少个模式串. 分析 : 如果你做过类似 Trie图 || AC自动机 + DP 类似的题目的话,那么这道题相对之 ...

  2. HDU - 4758 Walk Through Squares (AC自己主动机+DP)

    Description   On the beaming day of 60th anniversary of NJUST, as a military college which was Secon ...

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

    题意:给你两个串A,B, 问一个串长为M+N且包含A和B且恰好包含M个R的字符串有多少种组合方式,所有字符串中均只含有字符L和R. dp[i][j][k][S]表示串长为i,有j个R,在自动机中的状态 ...

  4. HDU 3920Clear All of Them I(状压DP)

    HDU 3920   Clear All of Them I 题目是说有2n个敌人,现在可以发n枚炮弹,每枚炮弹可以(可以且仅可以)打两个敌人,每一枚炮弹的花费等于它所行进的距离,现在要消灭所有的敌人 ...

  5. HDU 5067 Harry And Dig Machine(状压dp)

    HDU 5067 Harry And Dig Machine 思路:因为点才10个,在加上一个起点,处理出每一个点之间的曼哈顿距离,然后用状压dp搞,状态表示为: dp[i][s],表示在i位置.走过 ...

  6. HDU 3247 Resource Archiver(AC自动机 + 状压DP + bfs预处理)题解

    题意:目标串n( <= 10)个,病毒串m( < 1000)个,问包含所有目标串无病毒串的最小长度 思路:貌似是个简单的状压DP + AC自动机,但是发现dp[1 << n][ ...

  7. HDU - 6125: Free from square (状压DP+分组背包)

    problem:给定N,K.表示你有数1到N,让你最多选择K个数,问有多少种方案,使得选择的数的乘积无平方因子数.N,K<500: solution:显然可以状压DP做,但是500以内的素数还是 ...

  8. HDU 6984 - Tree Planting(数据分治+状压 dp)

    题面传送门 傻逼卡常屑题/bs/bs,大概现场过得人比较少的原因就是它比较卡常罢(Fog 首先对于这样的题我们很难直接维护,不过注意到这个 \(n=300\) 给得很灵性,\(k\) 比较小和 \(k ...

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

    Walk Through Squares Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Oth ...

随机推荐

  1. Android:adb shell 命令详解

    安卓系统是基于Linux系统开发,也就支持常见的Linux的命令,这些命令都保存在手机“/system/bin”的目录下,通过adb shell 便可以调用这些命令. 进入“/system/bin”该 ...

  2. MySQL学习-MySQL内置功能_索引与慢查询

    1.索引基础 1.1 介绍 (1.)为何要有索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂 ...

  3. webservice的一些理解

    web services中如果用.NET的话,DataSet可以作为与客户端交互的一个返回值,因为DataSet实质上是XML.而SOAP WSDL等都是基于XML的. --------------- ...

  4. 初识HTML标签

    web概念概述 JavaWeb: 使用Java语言开发基于互联网的项目 软件架构: C/S: Client/Server 客户端/服务器端 在用户本地有一个客户端程序,在远程有一个服务器端程序 如:Q ...

  5. spring cloud gateway自定义过滤器

    在API网关spring cloud gateway和负载均衡框架ribbon实战文章中,主要实现网关与负载均衡等基本功能,详见代码.本节内容将继续围绕此代码展开,主要讲解spring cloud g ...

  6. 【Linux 环境搭建】ubuntu 的samba配置

    在/etc/samba/smb.conf的文件末尾增加下面的内容然后重启samba [home] comment = James Harden path = / browseable = yes wr ...

  7. kafka生产者java客户端

    producer 包含一个用于保存待发送消息的缓冲池,缓冲池中消息是还没来得及传输到kafka集群的消息. 位于底层的kafka I/O线程负责将缓冲池中的消息转换成请求发送到集群.如果在结束prod ...

  8. 破解mysql

    https://blog.csdn.net/lian_easel/article/details/78734240 破解mysql

  9. Visual Studio 2019 密钥

    Visual Studio 2019 EnterpriseBF8Y8-GN2QH-T84XB-QVY3B-RC4DF Visual Studio 2019 ProfessionalNYWVH-HT4X ...

  10. Composer学习

    Composer简介 Composer是PHP的一个依赖管理工具,不是包管理器:在项目中声明所依赖的外部工具库(libraries),Composer会自动安装止血工具库及依赖的库文件. 安装方式 C ...