如标题所言,我已经沉迷于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. ubuntu lvm模式进行扩容

    ubuntu的16.04 18.04有lvm的功能(安装的时候的选项),能在磁盘空间用完的时候,无缝增加一个磁盘进去.因为linux系统只有一个盘,所以是非常方便,不会有windows加1个磁盘要进行 ...

  2. Window10家庭版启动hyper-v虚拟机组件

    在安装docker的时候发现如果直接使用docker for windows,对系统的要求是window10专业版或企业版,家庭版本身没有hyper-v,不能支持 虚拟化.但是后来我在搜索过程中发现, ...

  3. leetcode刷题笔记191 位1的个数

    题目描述: 编写一个函数,输入是一个无符号整数,返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量). 示例: 输入: 输出: 解释: 32位整数 的二进制表示为 . 题目分析: 判断3 ...

  4. Hbase RESTFul API创建namespace返回500

    1.使用官方提供的/namespaces/namespace创建namespace失败,返回500,官方提供示例:/namespaces/namespace POST 创建一个新的namespace. ...

  5. K-SVD字典学习及其实现(Python)

    算法思想 算法求解思路为交替迭代的进行稀疏编码和字典更新两个步骤. K-SVD在构建字典步骤中,K-SVD不仅仅将原子依次更新,对于原子对应的稀疏矩阵中行向量也依次进行了修正. 不像MOP,K-SVD ...

  6. 基于Python的信用评分卡模型分析(二)

    上一篇文章基于Python的信用评分卡模型分析(一)已经介绍了信用评分卡模型的数据预处理.探索性数据分析.变量分箱和变量选择等.接下来我们将继续讨论信用评分卡的模型实现和分析,信用评分的方法和自动评分 ...

  7. fetch上传文件

    通过简单的配置,实现form表单文件上传 var formData = new FormData(); var fileField = document.querySelector("inp ...

  8. “Hello World!团队”Final发布—视频链接+文案+美工

    视频发布:http://www.bilibili.com/video/av17022373/ 文案加美工:http://www.cnblogs.com/chjy/p/7990116.html SkyH ...

  9. 【Alpha】阶段第八次Scrum Meeting

    [Alpha]阶段第八次Scrum Meeting 工作情况 团队成员 今日已完成任务 明日待完成任务 刘峻辰 编写按学院搜索课程接口 编写获得所有学院接口 赵智源 构建前测试点测试框架 编写alph ...

  10. “私人助手”Beta版使用说明

    私人助手(Beta)版使用说明 私人助手这款软件是通过添加事件提醒功能,让用户能在正确的时间做正确的事情,使得工作变得更有效率,而这款软件的特色在于提醒模式的添加,用户可以通过震动.铃声提醒,我们的特 ...