落谷 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 ...
随机推荐
- Python_字符串_方法
#字典#把字符串中的字母提取出来改为大写并计数 a="aAsmr3idd4bgs7Dlsf9eAF" b1=[x for x in a if x.isalpha()] b=''.j ...
- Java 合并多个文件内容到一个文件(递归遍历某个文件夹下所有文件)
这段代码通过Java I/O流API实现将多个文件合并到一个文件中,输出为文本文件,提供一个支持语法高亮的网站,http://www.codeinword.com/ 适合粘贴代码到word文档,小巧实 ...
- [原题复现]SUCTF 2019 WEB EasySQL(堆叠注入)
简介 原题复现: 1 <?php 2 session_start(); 3 4 include_once "config.php"; 5 6 $post = array() ...
- addslashes()
addslashes() 函数返回在预定义字符之前添加反斜杠的字符串. 作用:防止sql注入
- node.js报错:Cannot find module 'xxx'的解决办法
从别处拷贝一份node.js项目,如图 控制台启动 nodemon index.js 后报错:Cannot find module xxx.删除node_modules,在启动时仍提示Cannot f ...
- 如何制作C语言基本数据类型的思维导图
在使用C语言编写程序时,数据类型是一个非常重要的内容,任何一个不被重视的数据错误都会使编译器无法翻译,导致程序报错. 使用思维导图来梳理各个数据类型是一个很有效的记忆方法,接下来就为大家展示一下我用i ...
- Vue Springboot (包括后端解决跨域)实现登录验证码功能详细完整版
利用Hutool 基于Vue.ElementUI.Springboot (跨域)实现登录验证码功能 前言 一.Hutool是什么? 二.下面开始步入正题:使用步骤 1.先引入Hutool依赖 2.控制 ...
- 2016年第七届蓝桥杯【C++省赛B组】F、G、H、J 题解
F. 方格填数 #深搜 题意 有\(10\)个格子,填入0~9的数字.要求:连续的两个数字不能相邻.(左右.上下.对角都算相邻),求可能的填数方案数. +--+--+--+ | | | | +--+- ...
- 趣文分享:C 语言和 C++、C# 的区别在什么地方?
任务: 把大象放到冰箱里.
- 【线程池】自己声明临时线程池一定要shutdown!
场景: 某个定时任务需要多线程执行,执行时间较久且每天只跑一次,想单独拉出一个线程池和其他业务隔离开,交给spring会导致核心线程一直存在 浪费线程资源,因此想单独拉一个池子用完就丢,原本想的是,在 ...