B 组都说看不懂……我也解释不清啊……只能写这么详细了

其实就是道板题

省流:f[i][s][j]表示字符串长度i,匹配情况s,ac自动机节点j

Problem Description

给定k个字符串以及长度为n的母串可选字母的集合,问母串要完整出现给定的k个字符串的方案数,答案模1000000007,字符仅包含小写字母。

Input

第一行两个整数n、k,表示字符串的长度和给定字符串的个数。

接下来k行每行一个字符串。

接下来一行1个整数m表示可选字母集合内元素个数。

接下来一行给出一个长为m的字符串,表示字母的集合(可能有重复)。

Output

一个整数ans,表示方案数。

Sample Input Copy

3 2
cr
rh
4
acrh

Sample Output Copy

1
【样例解释】
只有crh符合。

Data Constraint

30%的数据n<=10,m<=3。

60%的数据n<=40。

另有10%的数据k=0。

另有10%的数据m=1。

100%的数据n<=100,m<=10,k<=8,给定字符串长度<=30。


先想一个弱化版问题:给定 \(k\) 个模式串以及长度为 \(n\) 的母串可选字母的集合,对于一个母串,它的价值为出现模式串的个数。问所有合法母串的价值和。

怎么才能判定一个母串是否包含几个模式串?

我们可以想到 ac 自动机,考虑对模式串建 ac 自动机,定义 tail 为以一个节点为模式串结尾的个数。如果我们跑到了一个标记为 tail 的节点,说明我们的母串包含了这一个模式串。

模仿 ac 自动机的过程,用 \(f[i][j]\) 表示母串长度为 \(i\),走到了自动机上的节点 \(j\) 的价值和,然后枚举它的下一个字符 \(c\),明显有 \(f[i+1][son[j][c]]\gets f[i][j] + tail[son[j][c]]\)。


回到原问题,因为我们要求完整出现给定的 \(k\) 个模式串的方案数,所以我们状压模式串的出现情况为 \(s\)。

然后定义 tail 为以一个节点为模式串结尾的状压出现情况

同时,我们在 ac 自动机中有一个跳 fail 的步骤,这个步骤不是线性的,因为我们此时已经状压了,就可以直接在建树时把它传给子节点,有 \(tail[u]|=tail[fail[u]]\)。

所以我们设 \(f[i][s][j]\) 表示我们母串的长度为 \(i\),模式串的匹配状态为 \(s\)(状压后),当前母串跑到了 ac 自动机的节点 \(j\) 的方案数。

明显有 \(f[i+1][s|tail[son[j][c]]][son[j][c]]\gets f[i][s][j]\)。

#include <cstdio>
#include <queue>
using namespace std;
#define N 110
#define M 32
#define K 8
#define P 1000000007
int n, m, k, cnt, ans;
char s[M];
int can[M];
int f[2][1<<K][N*M];
int nxt[N*M][26];
int tail[N*M];
int fail[N*M];
bool vis[26];
void insert(int x) {
int p = 0;
for(int i = 1; s[i] != '\0'; i++) {
if(!nxt[p][s[i]-'a']) {
nxt[p][s[i]-'a'] = ++cnt;
}
p = nxt[p][s[i]-'a'];
}
tail[p] |= (1 << x);
}
void build() {
queue<int> q;
for(int i = 1; i <= m; i++)
if(nxt[0][can[i]]) q.push(nxt[0][can[i]]);
while(!q.empty()) {
int p = q.front();
q.pop();
tail[p] |= tail[fail[p]];
for(int i = 1; i <= m; i++) {
if(nxt[p][can[i]]) {
fail[nxt[p][can[i]]] = nxt[fail[p]][can[i]];
q.push(nxt[p][can[i]]);
} else {
nxt[p][can[i]] = nxt[fail[p]][can[i]];
}
}
}
}
int main() {
scanf("%d %d", &n, &k);
for(int i = 0; i < k; i++) {
scanf("%s", s+1);
insert(i);
}
scanf("%d", &m);
m = 0;
scanf("%s", s+1);
for(int i = 1; s[i] != '\0'; i++) {
if(!vis[s[i]-'a']) {
vis[s[i]-'a'] = 1;
can[++m] = s[i]-'a';
}
}
build();
f[0][0][0] = 1;
for(int i = 0; i < n; i++) {
for(int s = 0; s < (1<<k); s++) {
for(int p = 0; p <= cnt; p++) {
f[(i+1) % 2][s][p] = 0;
}
}
for(int s = 0; s < (1<<k); s++) {
for(int p = 0; p <= cnt; p++) {
if(!f[i%2][s][p]) continue;
for(int j = 1; j <= m; j++) {
int pp = nxt[p][can[j]];
(f[(i+1) % 2][s | tail[pp]][pp] += f[i%2][s][p]) %= P;
}
}
}
}
for(int i = 0; i <= cnt; i++) {
(ans += f[n%2][(1<<k)-1][i]) %= P;
}
printf("%d", ans);
}

【NOIP2013模拟联考8】匹配(match) 题解的更多相关文章

  1. JZOJ【NOIP2013模拟联考14】隐藏指令

    JZOJ[NOIP2013模拟联考14]隐藏指令 题目 Description 在d维欧几里得空间中,指令是一个长度为2N的串.串的每一个元素为d个正交基的方向及反方向之一.例如,d = 1时(数轴) ...

  2. JZOJ 3493. 【NOIP2013模拟联考13】三角形

    3493. [NOIP2013模拟联考13]三角形(triangle) (File IO): input:triangle.in output:triangle.out Time Limits: 10 ...

  3. JZOJ 3487. 【NOIP2013模拟联考11】剑与魔法(dragons)

    3487. [NOIP2013模拟联考11]剑与魔法(dragons) (Standard IO) Time Limits: 1000 ms  Memory Limits: 131072 KB  De ...

  4. JZOJ 3470. 【NOIP2013模拟联考8】最短路(path)

    470. [NOIP2013模拟联考8]最短路(path) (Standard IO) Time Limits: 1000 ms  Memory Limits: 262144 KB  Detailed ...

  5. JZOJ 3463. 【NOIP2013模拟联考5】军训

    3463. [NOIP2013模拟联考5]军训(training) (Standard IO) Time Limits: 2000 ms  Memory Limits: 262144 KB  Deta ...

  6. JZOJ 3462. 【NOIP2013模拟联考5】休息(rest)

    3462. [NOIP2013模拟联考5]休息(rest) (Standard IO) Time Limits: 1000 ms  Memory Limits: 262144 KB  Detailed ...

  7. JZOJ 3461. 【NOIP2013模拟联考5】小麦亩产一千八(kela)

    3461. [NOIP2013模拟联考5]小麦亩产一千八(kela) (Standard IO) Time Limits: 1000 ms  Memory Limits: 262144 KB  Det ...

  8. 【NOIP2013模拟联考7】OSU

    [NOIP2013模拟联考7]OSU 描述 Description osu 是一款群众喜闻乐见的休闲软件. 我们可以把osu的规则简化与改编成以下的样子: 一共有n次操作,每次操作只有成功与失败之分, ...

  9. [jzoj]3468.【NOIP2013模拟联考7】OSU!(osu)

    Link https://jzoj.net/senior/#main/show/3468 Description osu 是一款群众喜闻乐见的休闲软件. 我们可以把osu的规则简化与改编成以下的样子: ...

  10. 【NOIP2013模拟联考6】选课

    题目 你真的认为选课是那么容易的事吗?HYSBZ的ZY同志告诉你,原来选课也会让人产生一种想要回到火星的感觉.假设你的一周有n天,那么ZY编写的选课系统就会给你n堂课.但是该系统不允许在星期i和星期i ...

随机推荐

  1. vite ts 安装 js-cookie 库,vscode找不到类型说明(有波浪线),解决方案

    vite ts 安装 js-cookie 库,vscode找不到类型说明(有波浪线),解决方案 先安装库 https://www.npmjs.com/package/js-cookie 再安装类型 h ...

  2. vue3 markdown 读取文件的两种方法 有gitee发布地址

    方法一: markdown-loader html-loader import的时候就转换成html了,每次需要build,但是可以本地双击就能看,放哪个目录页不限制 方法二: axios + mar ...

  3. 基于泰凌微TLSR825x的物联网解决方案之ibeacon开发总结

    一 概念   iBeacon 是苹果公司2013年9月发布的移动设备用OS(iOS7)上配备的新功能.其工作方式是,配备有 低功耗蓝牙(BLE)通信功能的设备使用BLE技术向周围发送自己特有的ID,接 ...

  4. esp8266 I2C 实例解析及源码分析

    一  前言 作为一个方案商兼芯片开发者,研究芯片和功能实现除了基本的工作需要,还有一层就是也变成了一种职业习惯.从芯片到方案,发现很多方案公司的人水平都比较堪忧,只会调用api,根本不会看底层的代码实 ...

  5. html添加css样式的两种方法

      html添加css样式有三种方法,分别为行内式(使用style属性,在特定的HTML标签内使用).内嵌式(style标签把css代码放在特定页面的head部分中).外联式(使用link标签,将外部 ...

  6. Web安全前端基础

    Web安全前端基础 1.Web前端介绍 2.前端代码语言简单学习 一.Web前端介绍 web前端就是前端网络编程,也被认为是用户端编程,是为了网页或者网页应用,而编写HTML,CSS以及JS代码,所以 ...

  7. 修改Tomcat服务器Server Locations

    首先双击我们集成好的Tomcat服务器  修改Server Locations选项  Specify the server path (i.e. catalina.base) and deploy p ...

  8. 检验实时3D像素流送平台好坏的七个标准!(下)

    上篇文章我们介绍了<检验实时3D像素流送平台质量的七个标准>中的前四个标准,本文我们将继续给您介绍检验像素流送平台质量的其他三个标准. 您的平台是通过云还是仅通过渲染的图像传输数据? 您的 ...

  9. x5开源库后续知识点

    目录介绍 01.基础使用目录介绍 1.0.1 常用的基础介绍 1.0.2 Android调用Js 1.0.3 Js调用Android 1.0.4 WebView.loadUrl(url)流程 1.0. ...

  10. Cesium渲染模块之FBO与RBO

    1. 引言 Cesium是一款三维地球和地图可视化开源JavaScript库,使用WebGL来进行硬件加速图形,使用时不需要任何插件支持,基于Apache2.0许可的开源程序,可以免费用于商业和非商业 ...