落谷 P4052 [JSOI2007]文本生成器
题目链接。只要有一个可读就行,容斥会好做一点。
可读数量 \(=\) 总数 \(-\) 不可读数量
总数显然是 \(26 ^ n\)。
求解不可读数量
不可读数量可以利用 AC 自动机的模型进行 DP,把 \(AC\) 自动机上所有串的终点及他们在 fail 树上的子树全部染上非法,这样即求在 AC 自动机上走 \(m\) 步,不经过非法点的方案数?
朴素 \(DP\) (或者说递推的思想):
\(f[i][j]\) 表示前 \(i\) 个字符,当前在 AC 自动机上的节点编号是 \(j\) 的方案数。
设 \(u\) 点走一步能到 \(v\),显然:\(f[i][v] = \sum f[i - 1][u]\)。
复杂度 \(O(2600MN)\) 即 \(2600 * 6000\) 差不多 \(1e7\) 的亚子轻松跑过。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int L = 6005, M = 105, S = 26, P = 10007;
int n, m, q[L], f[M][L], tr[L][S], idx, fail[L];
bool e[L];
char s[M];
void insert() {
int len = strlen(s + 1), p = 0;
for (int i = 1; i <= len; i++) {
int ch = s[i] - 'A';
if (!tr[p][ch]) tr[p][ch] = ++idx;
p = tr[p][ch];
}
e[p] = true;
}
void build() {
int hh = 0, tt = -1;
for (int i = 0; i < 26; i++)
if (tr[0][i]) q[++tt] = tr[0][i];
while (hh <= tt) {
int u = q[hh++];
for (int i = 0; i < 26; i++) {
int v = tr[u][i];
if (v) {
fail[v] = tr[fail[u]][i];
if (e[fail[v]]) e[v] = true;
q[++tt] = v;
} else tr[u][i] = tr[fail[u]][i];
}
}
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%s", s + 1);
insert();
}
build();
f[0][0] = 1;
for (int i = 0; i < m; i++) {
for (int u = 0; u <= idx; u++) {
if (e[u] || !f[i][u]) continue;
for (int k = 0; k < 26; k++) {
int v = tr[u][k];
if (e[v]) continue;
(f[i + 1][v] += f[i][u]) %= P;
}
}
}
int ans = 1;
for (int i = 1; i <= m; i++) ans = ans * 26 % P;
for (int i = 0; i <= idx; i++)
if (!e[i]) ans = (ans - f[m][i] + P) % P;
printf("%d\n", ans);
return 0;
}
落谷 P4052 [JSOI2007]文本生成器的更多相关文章
- 洛谷P4052 [JSOI2007]文本生成器 AC自动机+dp
正解:AC自动机+dp 解题报告: 传送门! 感觉AC自动机套dp的题还挺套路的,,, 一般就先跑遍AC自动机,然后就用dp dp的状态一般都是f[i][j]:有i个字符,是ac自动机上的第j个节点, ...
- 洛谷P4052 [JSOI2007]文本生成器(AC自动机)
传送门 好像这题的确只能用AC自动机做了……Aufun大佬太强啦 正着难我们反着做,用总共单词个数减去没有一个单词都不包含的 然后考虑怎么处理一个单词都不包含的,就是跑不到单词的结尾节点 定义$f[i ...
- [洛谷P4052][JSOI2007]文本生成器
题目大意:有$n$个字符串$s_i$,问有多少个长度为$m$的字符串至少包含$n$个字符串中的一个,字符集 A-Z .$s_i,m\leqslant100,n\leqslant60$ 题解:$AC$自 ...
- P4052 [JSOI2007]文本生成器
P4052 [JSOI2007]文本生成器 AC自动机+dp 优秀题解传送门 设f[ i ][ j ]表示串的长度为 i ,当前在 j 点时不可识别的串的方案数 最后用总方案数减去不可识别方案数就是答 ...
- 2021.11.11 P4052 [JSOI2007]文本生成器(AC自动机+DP)
2021.11.11 P4052 [JSOI2007]文本生成器(AC自动机+DP) https://www.luogu.com.cn/problem/P4052 题意: JSOI 交给队员 ZYX ...
- BZOJ 1030: [JSOI2007]文本生成器 [AC自动机 DP]
1030: [JSOI2007]文本生成器 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 3953 Solved: 1614[Submit][Stat ...
- bzoj1030 [JSOI2007]文本生成器
1030: [JSOI2007]文本生成器 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 2654 Solved: 1100[Submit][Stat ...
- JSOI2007文本生成器
1030: [JSOI2007]文本生成器 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 1613 Solved: 656[Submit][Statu ...
- BZOJ 1030 [JSOI2007]文本生成器
1030: [JSOI2007]文本生成器 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 2624 Solved: 1087[Submit][Stat ...
随机推荐
- 算法:矩阵连乘(Java)动态规划
Description 给你2个矩阵A.B,我们使用标准的矩阵相乘定义C=AB如下: A数组中栏(column)的数目一定要等于B数组中列(row)的数目才可以做此2数组的相乘.若我们以rows(A) ...
- python编码规范以及推导式的编写
一.python 的编码规范
- java开发三年,Java中接口的使用你得知道,不然你凭什么涨薪
接口概述: 接口是Java语言中的一种引用类型,是方法的"集合",所以接口的内部主要就是定义方法,包含常量,抽象方法(JDK 7及以前),额外增加默认方法和静态方法(JDK 8), ...
- 如何在MathType输入手写体a
作为强大的数学公式编辑器,MathType中还能设置各种样式,还支持自定义设置,给大家编辑公式提供了更多的便利.那么有用户问:要如何将输入的字母a变为手写体呢?下面就来一起学习. 输入手写体a的步骤如 ...
- 宝塔Linux面板基础命令
安装宝塔Centos安装脚本 yum install -y wget && wget -O install.sh http://download.bt.cn/install/insta ...
- Linux中进程杀掉总是自动重启
<1> cat /proc/进程id/status 找到该子进程对应的父进程,将其父进
- 记 · ElemetnUI + Vue v-if 视图切换踩过的那些坑
使用EleUI 做一个用户登录窗口,需要用v-if 动态切换三个表单:手机登录.账密登录和密码找回.其中需要实现一个重置表单的功能,但其间出了一些小bug.密码找回表单中有三个表单项,手机登录和账密登 ...
- web服务器是啥
什么是web服务器 参考 https://www.cnblogs.com/zhaoyl/archive/2012/10/10/2718575.html 了解nginx之前,先了解下什么是web服务器吧 ...
- Codeforces Round #656 (Div. 3) 题解
A. Three Pairwise Maximums #构造 题目链接 题意 给定三个正整数\(x,y,z\),要求找出正整数\(a,b,c\),满足\(x=max(a,b), y=max(a,c), ...
- uniapp分包(详尽版)
PS:本文是笔者对基于uniapp的一小程序项目进行分包后的复盘文档,不足之处请多多指教. 一:分包相关概念 本质上是改变项目的路由以及优化项目各个模块的启动时间的一种优化技术. 主包与分包的概念 1 ...