如标题所言,我已经沉迷于AC自动机无法自拔了。。。

这又是一道AC自动的题,红红火火恍恍惚惚

穿越广场

[问题描述]

L 国的仪仗队要穿越首都广场了。首都广场可以看做是一块 N*M 的矩形网格,仪仗队要从左上角的格点(0,0)行进到右下角的格点(N,M),行进过程中只能向右走或者向下走。如果把向右走记为’R’,把向下走记为’D’,则仪仗队的行进序列是一个包含 M 个’R’和 N 个’D’的字符串。

这时,L 国的首长又提出了一个奇葩的要求。他认为仪仗队行走的序列中必须包含他给出的两个字符串。请你计算一下,满足首长要求的行进序列有多少种呢?

[输入]

第一行一个整数 T,表示数据组数。

每组数据的第一行是两个整数 M,N,表示行进序列由 M 个’R’ 和 N 个’D’ 构成。

每组数据的第二行和第三行是两个不相同的字符串,表示首长要求这两个字符串是行进序列的子串。

[输出]

一个整数,表示满足要求的行进序列的数量模 1000000007 的值

[输入输出样例]

Input

2

3 2

RRD

DDR

3 2

R

D

Output

1

10

[数据说明]

对于 50% 的数据,,字符串长度,T=1;

对于 100% 的数据,,字符串由’R’、’D’组成且长度

首先,部分分怎么搞咧,哎呀这不是重点,用 kmp+dp xjb搞一下就好了嘛,我要讲的是AC自动机

好的,满分算法,AC自动机上dp。

先讲一下做法:将给出的两个串建成AC自动机,然后在这个建好的AC自动机上跑dp,根据题目要求,路径需要包含给出的两个字符串,也就是说,在AC自动机上跑的时候需要经过两个叶子节点。我们设状态 f[i][j][k][0/1/2/3] 为,当前走了 i 步,其中有 j 步为 R ,当前走到的节点为 k ,两个叶子节点的经过情况为后面的0/1/2/3时的方案数。

这时有转移:

  f[i+1][j+1][ son[k]['R'] ][ l' ]+=f[i][j][k][l];

  f[i+1][j][ son[k]['D'] ][ l' ]+=f[i][j][k][l];

  ,,

当 son[k]['R'](son[k]['D'])为单词末尾时,l'=l |(1<<x(该单词编号,可以是0或1)),否则 l'=l;

所以最后的答案为:

下面是代码,注意,这题有一点很坑,它是先输的 M 再输的 N,我因为这个调了好久。。。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define mod (1000000007)
#define ll long long
#define il inline
#define RG register
using namespace std;
il int gi(){ RG int x=0,q=1; RG char ch=getchar(); while( ( ch<'0' || ch>'9' ) && ch!='-' ) ch=getchar();
  if( ch=='-' ) q=-1,ch=getchar(); while(ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x; }
il void File(){freopen("square.in","r",stdin); freopen("square.out","w",stdout);}

int T,n,m;
char s[110];

struct Trie{
   int son[210][2],fail[210],size,root;
   int val[210];
   il void init(){
      size=1;root=0;
      memset(f,0,sizeof(f));
      memset(son,0,sizeof(son));
      memset(val,0,sizeof(val));
      memset(fail,0,sizeof(fail));
   }

   il int idx(char c){ return c=='D'; }

   il void insert(char *s,int q){
      RG int cur=root;
      for(RG int i=0;s[i];i++){
         RG int id=idx(s[i]);
         if(!son[cur][id]) son[cur][id]=size++;
         cur=son[cur][id];
      }
      val[cur]|=1<<q; return ;
   }

   il void build(){
      int que[1010];
      RG int hd=0,tl=0;
      for(RG int i=0;i<2;i++)
         if(son[root][i]){
            que[tl++]=son[root][i];
            fail[son[root][i]]=root;
         }
         else son[root][i]=root;

      while(hd<tl){
         RG int cur=que[hd++];
         for(RG int i=0;i<2;i++){
            RG int Son=son[cur][i];
            if(Son){
               RG int f=fail[cur];
               while(f && !son[f][i]) f=fail[f];
               fail[Son]=son[f][i];
               val[Son]|=val[fail[Son]];
               que[tl++]=Son;
            }
            else son[cur][i]=son[fail[cur]][i];
         }
      }
   }

   ll f[210][110][210][4];//当前走了i步,其中有j步是R,现在在k这个节点,两种字符串的出现情况是l
   il void dp(){
      f[0][0][0][0]=1;
      for(RG int i=0;i<n+m;i++)
         for(RG int j=0;j<=m;j++)
            for(RG int k=0;k<size;k++)
               for(RG int l=0;l<4;l++)
                  if(f[i][j][k][l])
                     for(RG int t=(j==m);t<2;t++){
                        RG int Son=son[k][t];
                        RG int jj=j+(t==0);
                        RG int ss=l|val[Son];
                        (f[i+1][jj][Son][ss]+=f[i][j][k][l])%=mod;
                     }
      RG ll ret=0;
      for(RG int i=0;i<size;i++) (ret+=f[n+m][m][i][3])%=mod;
      printf("%lld\n",ret);
   }

}AC;

il void init(){
   m=gi(),n=gi(); AC.init();
   scanf("%s",s); AC.insert(s,0);
   scanf("%s",s); AC.insert(s,1);
   AC.build();
}

il void work(){ AC.dp(); }

int main(){ File(); T=gi(); while(T--){ init(); work(); } return 0; }

  

沉迷AC自动机无法自拔之:穿越广场 square的更多相关文章

  1. 沉迷AC自动机无法自拔之:[BZOJ2434] [Noi2011] 阿狸的打字机

    如标题所言,我已经沉迷于AC自动机无法自拔了... 这又是一道AC自动的题,红红火火恍恍惚惚 这题目做起来真舒服 简单概括一下:\(AC\)自动机\(fail\)树上树链剖分\(+\)树状数组 这种类 ...

  2. 沉迷AC自动机无法自拔之:[UVALive 4126] Password Suspects

    图片加载可能有点慢,请跳过题面先看题解,谢谢 一看到这么多模式串就非常兴奋,又是\(AC\)自动机 题目就是要求:经过 \(n\) 个节点,把所有单词都遍历一遍的方案数,和那道题差不多嘛 所以这样设: ...

  3. 沉迷AC自动机无法自拔之:[UVA 11468] Substring

    图片加载可能有点慢,请跳过题面先看题解,谢谢 这个鬼题目,上一波套路好了 先用题目给的模板串建\(AC\)自动机,把单词结尾标记为 \(val=1\),然后在建好的\(AC\)自动机上跑 \(dp\) ...

  4. 基于trie树做一个ac自动机

    基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...

  5. AC自动机-算法详解

    What's Aho-Corasick automaton? 一种多模式串匹配算法,该算法在1975年产生于贝尔实验室,是著名的多模式匹配算法之一. 简单的说,KMP用来在一篇文章中匹配一个模式串:但 ...

  6. python爬虫学习(11) —— 也写个AC自动机

    0. 写在前面 本文记录了一个AC自动机的诞生! 之前看过有人用C++写过AC自动机,也有用C#写的,还有一个用nodejs写的.. C# 逆袭--自制日刷千题的AC自动机攻克HDU OJ HDU 自 ...

  7. BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2545  Solved: 1419[Submit][Sta ...

  8. BZOJ 3172: [Tjoi2013]单词 [AC自动机 Fail树]

    3172: [Tjoi2013]单词 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 3198  Solved: 1532[Submit][Status ...

  9. BZOJ 1212: [HNOI2004]L语言 [AC自动机 DP]

    1212: [HNOI2004]L语言 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1367  Solved: 598[Submit][Status ...

随机推荐

  1. [工具]chrome添加crx扩展程序(附禁止复制破解扩展)

    Hello亲爱的观众朋友们大家好,我是09. 今天带来墙内用户安装chrome插件的方法. 1.打开扩展程序 2.把crx往里拖,欧了. ps.顺带安利chrome禁止复制破解扩展Enable Cop ...

  2. Redis初探(windows/linux安装)

    最近在学习Redis,先看看简介: Redis 是完全开源免费的,遵守BSD协议(可以自由的使用,修改源代码的协议,当然需要满足一定的条件),是一个高性能的key-value数据库. 特点&& ...

  3. ETSI公布的多接入移动边缘计算概念验证

    ETSI多接入移动边缘计算 公布的概念验证如下: 来源 MEC PoC Projects PoC#1: "Video User Experience Optimization via MEC ...

  4. vscode调试js,安装了nodejs之后还出现无法在Path上找到运行时的node

    vscode 调试js,安装了nodejs之后还出现无法在Path上找到运行时的node. 重启vscode解决

  5. CHAPTER 38 Reading ‘the Book of Life’ The Human Genome Project 第38章 阅读生命之书 人体基因组计划

    CHAPTER 38 Reading ‘the Book of Life’ The Human Genome Project 第38章 阅读生命之书 人体基因组计划 Humans have about ...

  6. 简介几种系统调用函数:write、read、open、close、ioctl

    在 Linux 中,一切(或几乎一切)都是文件,因此,文件操作在 Linux 中是十分重要的,为此,Linux 系统直接提供了一些函数用于对文件和设备进行访问和控制,这些函数被称为系统调用(sysca ...

  7. linux命令系列 grep

    grep, egrep, fgrep - print lines matching a pattern SYNOPSIS grep [OPTIONS] PATTERN [FILE...] grep [ ...

  8. 解决iscroll.js上拉下拉刷新手指划出屏幕页面无法回弹问题

    博客已迁移至http://zlwis.me. 使用过iscroll.js的上拉下拉刷新效果的朋友应该都碰到过这个问题:在iOS的浏览器中,上拉或下拉刷新时,当手指划出屏幕后,页面无法弹回.很多人因为解 ...

  9. ClickOnce 创建桌面快捷方式

    static void Main() { bool bCreatedNew; Mutex m = new Mutex(false, "TestClickOnceClientName" ...

  10. iOS开发学习-资源打包

    图片是被放到Images.xcassets中 1.部署版本在>=iOS8的时候,打包的资源包中的图片会被放到Assets.car 图片被压缩: 2.部署版本在<iOS8的时候,打包的资源包 ...