沉迷AC自动机无法自拔之:穿越广场 square
如标题所言,我已经沉迷于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的更多相关文章
- 沉迷AC自动机无法自拔之:[BZOJ2434] [Noi2011] 阿狸的打字机
如标题所言,我已经沉迷于AC自动机无法自拔了... 这又是一道AC自动的题,红红火火恍恍惚惚 这题目做起来真舒服 简单概括一下:\(AC\)自动机\(fail\)树上树链剖分\(+\)树状数组 这种类 ...
- 沉迷AC自动机无法自拔之:[UVALive 4126] Password Suspects
图片加载可能有点慢,请跳过题面先看题解,谢谢 一看到这么多模式串就非常兴奋,又是\(AC\)自动机 题目就是要求:经过 \(n\) 个节点,把所有单词都遍历一遍的方案数,和那道题差不多嘛 所以这样设: ...
- 沉迷AC自动机无法自拔之:[UVA 11468] Substring
图片加载可能有点慢,请跳过题面先看题解,谢谢 这个鬼题目,上一波套路好了 先用题目给的模板串建\(AC\)自动机,把单词结尾标记为 \(val=1\),然后在建好的\(AC\)自动机上跑 \(dp\) ...
- 基于trie树做一个ac自动机
基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...
- AC自动机-算法详解
What's Aho-Corasick automaton? 一种多模式串匹配算法,该算法在1975年产生于贝尔实验室,是著名的多模式匹配算法之一. 简单的说,KMP用来在一篇文章中匹配一个模式串:但 ...
- python爬虫学习(11) —— 也写个AC自动机
0. 写在前面 本文记录了一个AC自动机的诞生! 之前看过有人用C++写过AC自动机,也有用C#写的,还有一个用nodejs写的.. C# 逆袭--自制日刷千题的AC自动机攻克HDU OJ HDU 自 ...
- BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2545 Solved: 1419[Submit][Sta ...
- BZOJ 3172: [Tjoi2013]单词 [AC自动机 Fail树]
3172: [Tjoi2013]单词 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 3198 Solved: 1532[Submit][Status ...
- BZOJ 1212: [HNOI2004]L语言 [AC自动机 DP]
1212: [HNOI2004]L语言 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1367 Solved: 598[Submit][Status ...
随机推荐
- Python之pexpect详解
一.引子 Pexpect程序主要用于人机对话的模拟,就是那种系统提问,人来回答yes/no,或者账号登陆输入用户名和密码等等的情况.因为这种情况特别多而且繁琐,所以很多语言都有各种自己的实现.最初的第 ...
- javascript this(上)
javascript的this指向的是一个函数运行时动态绑定对象. this的4种常见的指向: 作为对象的方法调用 var obj={ name:"姚小白", getName:fu ...
- yocto-sumo源码解析(十): ProcessServer.idle_commands
这一节开始介绍ProcessServer.idle_commands,前面我们知道ProcessServer.main就是不停调用idle_commands()以获取可用的套接字描述符或者是文件描述符 ...
- Redis源码阅读(五)集群-故障迁移(上)
Redis源码阅读(五)集群-故障迁移(上) 故障迁移是集群非常重要的功能:直白的说就是在集群中部分节点失效时,能将失效节点负责的键值对迁移到其他节点上,从而保证整个集群系统在部分节点失效后没有丢失数 ...
- k倍区间:前缀和
[蓝桥杯][2017年第八届真题]k倍区间 题目描述 给定一个长度为N的数列,A1, A2, ... AN,如果其中一段连续的子序列Ai, Ai+1, ... Aj(i <= j)之和是K的倍数 ...
- 华策光通信: LED可见光通信室内定位项目获最具投资价值奖
3月21日上午,一场持续3个多小时的O2O领域的创业DemoShow在深圳科兴科学园会议中心激烈上演.来自华策光通信的基于LED可见光通信室内精准定位项目作为LED与室内定位领域的跨界融合项目经过精彩 ...
- D.王者荣耀交流协会——PSP Daily(测评人:贾男男)
D.王者荣耀交流协会——PSP Daily(测评人:贾男男) 一.基于NABCD评论作品,及改进建议 每个小组评论其他小组beta发布的作品.1.根据(不限于)NABCD评论作品的选题;2.评论作品对 ...
- 第七周psp例行报告
本周psp 本周进度条 代码累积折线图 博文字数累积折线图 饼状图
- Linux第一二章笔记
第一章 Linux内核简介 1. Unix内核的特点 简洁:仅提供系统调用并有一个非常明确的设计目的 抽象:几乎所有东西都被当做文件 可移植性:使用C语言编写,使得其在各种硬件体系架构面前都具备令人惊 ...
- web11 Struts处理表单数据
电影网站:www.aikan66.com 项目网站:www.aikan66.com游戏网站:www.aikan66.com图片网站:www.aikan66.com书籍网站:www.aikan66.co ...