题意 : 给出一个 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. win10安装anaconda及tensorflow1.9版本

    前言 因为之前的anaconda的conda命令不能用,又找不到原因,所以就决定重装anaconda,然后再装个tensorflow环境.. 正文 可以去官网下载,也可以去清华的开源软件镜像站下载ht ...

  2. Sql注入校验

    /// <summary> /// Sql注入校验 /// </summary> /// <param name="listWord">字符&l ...

  3. 无法在发送 HTTP 标头之后进行重定向

    public ActionResult Index2() { Response.Buffer = true; Response.Clear(); return Redirect("/Wech ...

  4. SQL Server之索引解析(一)

    SQL Server之索引解析(一)   1.写在前面 微软专门给出SQL Server设计思路及实现路线,从7大体系结构阐述是如何实现,通过了解这些,我们就可以总结出数据库设计原则.编程中sql写法 ...

  5. dajngo ORM查询中select_related的作用,博客主题的定制,从数据库中按照年月筛选时间

    1.dajngo ORM查询中select_related的作用 select_related()方法一次性的把数据库关联的对象都查询出来放入对象中,再次查询时就不需要再连接数据库,节省了后面查询数据 ...

  6. java中关键字final,finally,finalize的区别

    -final:作为修饰符关键字,有三种用法: 1,如果一个类被声明为final,则意味着它不能被继承. 2,将变量声明为final,则表示它是一个常量,也就是保证它在使用过程中不被修改,被final修 ...

  7. 使用GET与POST方式获取html数据

    抓取网站数据解析的工作,其中,使用到GET和POST方法获取html数据. 使用GET方式: /** * 使用get方式获取html数据 * * @param strURL(需要访问的网站) * @r ...

  8. 编辑SE16N表的函数

    函数:SE16N_INTERFACE 此外还可以SE16N 输入对应的查询条件后执行debug该变量 GD-SAPEDIT = ‘X’ 和GD-EDIT = ‘X’ 来实现当前SE16N 中该表的编辑

  9. linux后台运行springboot项目

    首先需要进到自己springboot项目的根目录,然后执行如下linux命令 nohup java -jar 自己的springboot项目.jar >日志文件名.log 2>&1 ...

  10. $strobe$monitor$display

      $strobe:当该时刻的所有事件处理完后,在这个时间步的结尾打印一行格式化的文本,语法$strobe( Argument,...);$fstrobe( Mcd, Argument,...);Mc ...