Problem E: Passwords

\[Time Limit: 1 s \quad Memory Limit: 256 MiB
\]

题意

给出两个正整数\(A,B\),再给出\(n\)个字符串,然后问你满足条件的字符串有多少种,最后答案\(\%1e6+3\)。条件如下

\[\begin{aligned}
1、&长度在A到B之间\\
2、&所有子串不存在n个字符串中任意一个\\
3、&模式串中,把0看成o,1看成i,3看成e,5看成s,7看成t\\
4、&至少存在一个小写字母,一个大写字母,一个数字
\end{aligned}
\]

要注意一下题目中的Additionally, for the purposes of avoiding the blacklist, you cannot use \(l33t\).这句话,我一开始还以为\(l33t\)也算第\(n+1\)个字符串,也不能计数,结果发现读错了,这句话只是引出后面那么限制条件。

思路

很显然这种在多个字符串上跳来跳去的,然后给出一些限制条件,在\(AC自动机\)上\(DP\)大部分情况下是\(ok\)的,而且对\(fail\)指针\(build\)时,也很常见,补全成\(Trie\)图,把\(fail[u]\)的信息传给\(u\)就可以了。

那么如何\(dp\)呢,用\(dp[state][i][j]\),\(state\)最大为\(7\),第一位为小写字母,第二问为大写字母,第三次为数字,状压状态,\(i\)表示匹配串已经到了第\(i\)位,\(j\)表示在\(AC自动机\)上的状态,然后状态就很容易得到了。

\[\begin{aligned}
dp[st][i][j] &-> dp[st|1][i+1][k] 小写字母时\\
dp[st][i][j] &-> dp[st|2][i+1][k] 大写字母时\\
dp[st][i][j] &-> dp[st|4][i+1][k] 数字时\\
\end{aligned}
\]

最后输出\(dp[7][\sum_A^B][\sum_1^{sz}]\)就可以了。

/***************************************************************
> File Name : E.cpp
> Author : Jiaaaaaaaqi
> Created Time : 2019年05月08日 星期三 15时00分56秒
***************************************************************/ #include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lowbit(x) x & (-x)
#define mes(a, b) memset(a, b, sizeof a)
#define fi first
#define se second
#define pii pair<int, int> typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 5e3 + 10;
const int maxm = 1e5 + 10;
const ll mod = 1e6 + 3;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-8;
using namespace std; int n, m, A, B;
int cas, tol, T; map<int, int> mp; void handle() {
mp.clear();
for(int i='a'; i<='z'; i++) {
mp[i] = i-'a'+1;
}
for(int i='A'; i<='Z'; i++) {
mp[i] = i-'A'+1;
}
int cnt = 26;
for(int i='0'; i<='9'; i++) {
if(i=='0') mp[i] = mp['o'];
else if(i == '1') mp[i] = mp['i'];
else if(i == '3') mp[i] = mp['e'];
else if(i == '5') mp[i] = mp['s'];
else if(i == '7') mp[i] = mp['t'];
else mp[i] = ++cnt;
}
}
struct AC {
int node[maxn][35], fail[maxn], cnt[maxn];
ll dp[10][25][maxn];
int root, sz;
int newnode() {
mes(node[++sz], 0);
cnt[sz] = 0;
return sz;
}
void init() {
sz = 0;
root = newnode();
}
void insert(char *s) {
int len = strlen(s+1);
int rt = root;
for(int i=1; i<=len; i++) {
int k = mp[s[i]];
if(node[rt][k] == 0) node[rt][k] = newnode();
rt = node[rt][k];
}
cnt[rt] = 1;
}
void build() {
queue<int> q;
while(!q.empty()) q.pop();
fail[root] = root;
for(int i=1; i<=31; i++) {
if(node[root][i] == 0) {
node[root][i] = root;
} else {
fail[node[root][i]] = root;
q.push(node[root][i]);
}
}
while(!q.empty()) {
int u = q.front();
cnt[u] |= cnt[fail[u]];
q.pop();
for(int i=1; i<=31; i++) {
if(node[u][i] == 0) {
node[u][i] = node[fail[u]][i];
} else {
fail[node[u][i]] = node[fail[u]][i];
q.push(node[u][i]);
}
}
}
}
ll solve(int A, int B) {
for(int i=0; i<=7; i++) {
for(int j=0; j<=B; j++) {
for(int k=0; k<=sz; k++) {
dp[i][j][k] = 0;
}
}
}
dp[0][0][1] = 1;
for(int i=0; i<B; i++) {
for(int j=1; j<=sz; j++) {
if(cnt[j]) continue;
for(int st=0; st<=7; st++) {
if(dp[st][i][j] == 0) continue;
// printf("dp[%d][%d][%d] = %lld\n", st, i, j, dp[st][i][j]);
for(int k='a'; k<='z'; k++) {
int nst = node[j][mp[k]];
if(cnt[nst]) continue;
dp[st|1][i+1][nst] += dp[st][i][j];
dp[st|2][i+1][nst] += dp[st][i][j];
dp[st|1][i+1][nst] %= mod;
dp[st|2][i+1][nst] %= mod;
}
for(int k='0'; k<='9'; k++) {
int nst = node[j][mp[k]];
if(cnt[nst]) continue;
dp[st|4][i+1][nst] += dp[st][i][j];
dp[st|4][i+1][nst] %= mod;
}
}
}
}
ll ans = 0;
for(int i=A; i<=B; i++) {
for(int j=1; j<=sz; j++) {
if(dp[7][i][j] == 0) continue;
// printf("dp[7][%d][%d] = %lld\n", i, j, dp[7][i][j]);
ans = (ans + dp[7][i][j])%mod;
}
}
return ans;
}
} ac;
char s[maxn]; int main() {
handle();
ac.init();
scanf("%d%d", &A, &B);
scanf("%d", &n);
for(int i=1; i<=n; i++) {
scanf("%s", s+1);
ac.insert(s);
}
ac.build();
ll ans = ac.solve(A, B);
printf("%lld\n", ans);
return 0;
}

Passwords Gym - 101174E (AC自动机上DP)的更多相关文章

  1. 【洛谷4045】[JSOI2009] 密码(状压+AC自动机上DP)

    点此看题面 大致题意: 给你\(n\)个字符串,问你有多少个长度为\(L\)的字符串,使得这些字符串都是它的子串.若个数不大于\(42\),按字典序输出所有方案. 状压 显然,由于\(n\)很小,我们 ...

  2. bzoj [Sdoi2014]数数 AC自动机上dp

    [Sdoi2014]数数 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1264  Solved: 636[Submit][Status][Discu ...

  3. 【Luogu】P3311数数(AC自动机上DP)

    题目链接 蒟蒻今天终于学会了AC自动机,感觉很稳 (后一句愚人节快乐) 这题开一个f[i][j][k]表示有没有受到限制,正在枚举第j位,来到了AC自动机的第k个节点 的方案数 随后可以刷表更新 注意 ...

  4. URAL 1158 AC自动机上的简单DP+大数

    题目大意 在一种语言中的字母表中有N(N<=50)个字母,每个单词都由M(M<=50)个字母构成,因此,一共可以形成N^M个单词.但是有P(P<=10)个串是被禁止的,也就是说,任何 ...

  5. bzoj4032/luoguP4112 [HEOI2015]最短不公共子串(后缀自动机+序列自动机上dp)

    bzoj4032/luoguP4112 [HEOI2015]最短不公共子串(后缀自动机+序列自动机上dp) bzoj Luogu 题解时间 给两个小写字母串 $ A $ , $ B $ ,请你计算: ...

  6. POJ 3691 AC自动机上的dp

    题目大意: 给定一些不合理的DNA序列,再给一段较长的dna序列,问最少修改几次可以使序列中不存在任何不合理序列,不能找到修改方法输出-1 这里你修改某一个点的DNA可能会影响后面,我们不能单纯的找匹 ...

  7. HNU 13108-Just Another Knapsack Problem (ac自动机上的dp)

    题意: 给你一个母串,多个模式串及其价值,求用模式串拼接成母串(不重叠不遗漏),能获得的最大价值. 分析: ac自动机中,在字典树上查找时,用dp,dp[i]拼成母串以i为结尾的子串,获得的最大价值, ...

  8. 【BZOJ1030】[JSOI2007] 文本生成器(AC自动机上跑DP)

    点此看题面 大致题意: 给你\(N\)个字符串(只含大写字母),要你求出有多少个由\(M\)个大写字母构成的字符串含有这\(N\)个字符串中的至少一个. \(AC\)自动机 看到题目,应该比较容易想到 ...

  9. BZOJ 1030 文本生成器 | 在AC自动机上跑DP

    题目: http://www.lydsy.com/JudgeOnline/problem.php?id=1030 题解: 鸽 #include<cstdio> #include<al ...

随机推荐

  1. DDR3(1):IP核调取

    本系列整理一下基于 Xilinx A7 芯片的 DDR3 的使用,此处采用的 DDR3 IP核为软核,即采用 FPGA 逻辑单元.寄存器.查找表等搭建出来 IP核.从 IP 核的调取开始,接着读写测试 ...

  2. Ubuntu 18 Kubernetes集群的安装和部署 以及Helm的安装

    首先说一下我的环境, 我是在windows 10 上面建了一个ubuntu18的虚拟机,同时由于某些原因 不受网络限制, 所以安装比较顺利. Install 1.安装并启用 Docker  sudo ...

  3. 什么是k8s

    •Kubernetes介绍 1.背景介绍 云计算飞速发展 - IaaS - PaaS - SaaS Docker技术突飞猛进 - 一次构建,到处运行 - 容器的快速轻量 - 完整的生态环境 2.什么是 ...

  4. .Net Core 程序集管理说明(加载)

    .NET CORE 的程序集加载管理和以前的 .NET 发生了很大的变化, 在 .NET CORE 里, 程序集的加载, 依赖了 xx.deps.json 文件, deps.json 文件里,定义了程 ...

  5. .NET CORE 动态加载 DLL 的问题

    有个系统, 需要适应不同类型的数据库(同时只使用其中一种),如果把数据库操作层提取出来,然后针对不同的数据库使用不同的 DLL, 再根据不同的项目使用不同的库, 在以前的 ASP.NET 中, 直接把 ...

  6. English--七种句子成分概述

    English|七种句子成分概述 现代英语的语法是非常严谨的,英语句子的成分与汉语的句子成分有很大的区别.所以在学习语法的开始,需要上文讲到的句型作为骨架支撑,还需要明白句子的成分是什么,以及个各自的 ...

  7. VC 在桌面上绘制一些图形

    注意:这是在桌面上绘制图形.如果想在VC++ MFC工程的视窗口上绘制图形.可以这么来,在工程View类的一个菜单响应(或者鼠标单击等事件的的响应)函数中添加下面main 中的代码,只需要将“红色字体 ...

  8. golang中uint8字节切片转字符串

    假如拿到了一个字节切片test1 = {'a', 'b', 'c', 'd', 11} package main import ( "fmt" "reflect" ...

  9. Weshop基于Spring Cloud开发的小程序商城系统

    WESHOP | 基于微服务的小程序商城系统 Weshop是基于Spring Cloud(Greenwich)开发的小程序商城系统,提供整套公共微服务服务模块,包含用户中心.商品中心.订单中心.营销中 ...

  10. java集合学习(2):Map和HashMap

    Map接口 java.util 中的集合类包含 Java 中某些最常用的类.最常用的集合类是 List 和 Map. Map 是一种键-值对(key-value)集合,Map 集合中的每一个元素都包含 ...