落谷 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 ...
随机推荐
- leetcode bitmap系列问题整理
1. 题目: 编写一个函数,输入是一个无符号整数,返回其二进制表达式中数字位数为 '1' 的个数(也被称为汉明重量). 示例 : 输入: 11输出: 3解释: 整数 11 的二进制表示为 000000 ...
- select实现超时(套接字IO超时设置)
实现超时的三种方式: 1.SIGALARM信号 void handler(int sig) { return 0; } signal(SIGALRM,handler); alarm(5); int ...
- fcntl函数用法——复制文件描述符
文件描述符复制和输出重定向dup() 用最小的文件描述符来复制,从0开始搜素.复制文件描述符后,最小文件描述符指向被复制描述符指向的文件.dup2(int oldfd,int newfd) 强制用ne ...
- mysql之多表查询的其他查询
1,临时表查询 (1)需求:查询高于本部门平均工资的人员 select * from person as p, (select dept_id, avg(salary) as '平均工资' from ...
- C++中new和malloc区别
面试中new和malloc区别会被经常问到,审视了自己,发现不知道该怎么表达 整理一下: 1.从属性 new/delete是C++关键字,需要编译器支持: malloc/free是库函数,需要头文件支 ...
- Elements-of-Python01_Input/Output
(内容包括输入input,输出print,注释comment,预测类型转换eval,命名与赋值Name & Bestow) 输入Input 和 输出Print Python中利用input() ...
- Android应用测试指南
一.Android 的 SDK Windows 版本安装 按顺序安装以下内容 1. 安装JDK(Java Development Kit, 即Java开发工具包) 2. 安装Eclipse 集成 ...
- python 工业日志模块 未来的python日志最佳实践
目录 介绍 好的功能 安装方法 参数介绍 呆log 参数与 使用方法 版本说明 后期版本规划 todo 感谢 介绍 呆log:工业中,python日志模块,安装即用.理论上支持 python2, py ...
- LNMP 一键安装脚本
这个脚本是使用shell编写,为了快速在生产环境上部署lnmp/lamp/lnmpa(Linux.Nginx/Tengine/OpenResty.MySQL/MariaDB/Percona.PHP), ...
- Spring MVC系列-(5) AOP
5 AOP 5.1 什么是AOP AOP(Aspect-Oriented Programming,面向切面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的 ...