POJ 1625 Censored!(AC自动机 + DP + 大数 + 拓展ASCII处理)题解
题意:给出n个字符,p个病毒串,要你求出长度为m的不包含病毒串的主串的个数
思路:不给取模最恶劣情况$50^{50}$,所以用高精度板子。因为m比较小,可以直接用DP写。
因为给你的串的字符包含拓展ASCII码(128~256),由于编译器的原因,char的读入范围在-128~127或者0~255之间不确定,所以你读一个拓展ASCII码的字符后可能是负的,那么你处理的时候要注意加130。或者你直接用map映射。或者用unsigned char。
代码:
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 100 + 5;
const int M = 50 + 5;
const ull seed = 131;
const double INF = 1e20;
const int MOD = 100000;
int n, m, p;
int tol;
int reflect[600];
struct BigInt{
const static int mod = 10000;
int a[50], len;
BigInt(){
memset(a, 0, sizeof(a));
len = 1;
}
void set(int v){
memset(a, 0, sizeof(a));
len = 0;
do{
a[len++] = v % mod;
v /= mod;
}while(v);
} BigInt operator + (const BigInt &b) const{
BigInt res;
res.len = max(len, b.len);
for(int i = 0; i <= res.len; i++)
res.a[i] = 0;
for(int i = 0; i < res.len; i++){
res.a[i] += ((i < len)? a[i] : 0) + ((i < b.len)? b.a[i] : 0);
res.a[i + 1] += res.a[i] / mod;
res.a[i] %= mod;
}
if(res.a[res.len] > 0) res.len++;
return res;
} BigInt operator * (const BigInt &b) const{
BigInt res;
for(int i = 0; i < len; i++){
int up = 0;
for(int j = 0; j < b.len; j++){
int temp = a[i] * b.a[j] + res.a[i + j] + up;
res.a[i + j] = temp % mod;
up = temp / mod;
}
if(up != 0) res.a[i + b.len] = up;
}
res.len = len + b.len;
while(res.a[res.len - 1] == 0 && res.len > 1) res.len--;
return res;
} void output(){
printf("%d", a[len - 1]);
for(int i = len - 2; i >= 0; i--){
printf("%04d", a[i]);
}
printf("\n");
}
};
BigInt dp[55][maxn];
struct Aho{
struct state{
int next[51];
int fail, cnt;
}node[maxn];
int size;
queue<int> q; void init(){
size = 0;
newtrie();
while(!q.empty()) q.pop();
} int newtrie(){
memset(node[size].next, 0, sizeof(node[size].next));
node[size].cnt = node[size].fail = 0;
return size++;
} void insert(char *s){
int len = strlen(s);
int now = 0;
for(int i = 0; i < len; i++){
int c = reflect[int(s[i]) + 130];
if(node[now].next[c] == 0){
node[now].next[c] = newtrie();
}
now = node[now].next[c];
}
node[now].cnt = 1;
} void build(){
node[0].fail = -1;
q.push(0); while(!q.empty()){
int u = q.front();
q.pop();
if(node[node[u].fail].cnt && u) node[u].cnt = 1;
for(int i = 0; i < 51; i++){
if(!node[u].next[i]){
if(u == 0)
node[u].next[i] = 0;
else
node[u].next[i] = node[node[u].fail].next[i];
}
else{
if(u == 0) node[node[u].next[i]].fail = 0;
else{
int v = node[u].fail;
while(v != -1){
if(node[v].next[i]){
node[node[u].next[i]].fail = node[v].next[i];
break;
}
v = node[v].fail;
}
if(v == -1) node[node[u].next[i]].fail = 0;
}
q.push(node[u].next[i]);
}
}
}
} void query(){
BigInt one;
one.set(1);
for(int i = 0; i <= m; i++){
for(int j = 0; j < size; j++){
dp[i][j].set(0);
}
}
for(int i = 0; i < tol; i++){
if(node[node[0].next[i]].cnt == 0){
dp[1][node[0].next[i]] = dp[1][node[0].next[i]] + one;
}
}
for(int i = 1; i <= m; i++){
for(int j = 0; j < size; j++){
for(int k = 0; k < tol; k++){
if(node[node[j].next[k]].cnt == 0){
dp[i + 1][node[j].next[k]] = dp[i + 1][node[j].next[k]] + dp[i][j];
}
}
}
}
BigInt ans;
ans.set(0);
for(int i = 0; i < size; i++){
if(node[i].cnt == 0){
ans = ans + dp[m][i];
}
}
ans.output();
} }ac;
char s[100];
int main(){
while(~scanf("%d%d%d", &n, &m, &p)){
scanf("%s", s);
tol = 0;
for(int i = 0; i < n; i++){
reflect[int(s[i]) + 130] = tol++;
}
ac.init();
while(p--){
scanf("%s", s);
ac.insert(s);
}
ac.build();
ac.query();
}
return 0;
}
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 100 + 5;
const int M = 50 + 5;
const ull seed = 131;
const double INF = 1e20;
const int MOD = 100000;
int n, m, p;
int tol;
map<char, int> reflect;
struct BigInt{
const static int mod = 10000;
int a[50], len;
BigInt(){
memset(a, 0, sizeof(a));
len = 1;
}
void set(int v){
memset(a, 0, sizeof(a));
len = 0;
do{
a[len++] = v % mod;
v /= mod;
}while(v);
} BigInt operator + (const BigInt &b) const{
BigInt res;
res.len = max(len, b.len);
for(int i = 0; i <= res.len; i++)
res.a[i] = 0;
for(int i = 0; i < res.len; i++){
res.a[i] += ((i < len)? a[i] : 0) + ((i < b.len)? b.a[i] : 0);
res.a[i + 1] += res.a[i] / mod;
res.a[i] %= mod;
}
if(res.a[res.len] > 0) res.len++;
return res;
} BigInt operator * (const BigInt &b) const{
BigInt res;
for(int i = 0; i < len; i++){
int up = 0;
for(int j = 0; j < b.len; j++){
int temp = a[i] * b.a[j] + res.a[i + j] + up;
res.a[i + j] = temp % mod;
up = temp / mod;
}
if(up != 0) res.a[i + b.len] = up;
}
res.len = len + b.len;
while(res.a[res.len - 1] == 0 && res.len > 1) res.len--;
return res;
} void output(){
printf("%d", a[len - 1]);
for(int i = len - 2; i >= 0; i--){
printf("%04d", a[i]);
}
printf("\n");
}
};
BigInt dp[55][maxn];
struct Aho{
struct state{
int next[51];
int fail, cnt;
}node[maxn];
int size;
queue<int> q; void init(){
size = 0;
newtrie();
while(!q.empty()) q.pop();
} int newtrie(){
memset(node[size].next, 0, sizeof(node[size].next));
node[size].cnt = node[size].fail = 0;
return size++;
} void insert(char *s){
int len = strlen(s);
int now = 0;
for(int i = 0; i < len; i++){
int c = reflect[s[i]];
if(node[now].next[c] == 0){
node[now].next[c] = newtrie();
}
now = node[now].next[c];
}
node[now].cnt = 1;
} void build(){
node[0].fail = -1;
q.push(0); while(!q.empty()){
int u = q.front();
q.pop();
if(node[node[u].fail].cnt && u) node[u].cnt = 1;
for(int i = 0; i < 51; i++){
if(!node[u].next[i]){
if(u == 0)
node[u].next[i] = 0;
else
node[u].next[i] = node[node[u].fail].next[i];
}
else{
if(u == 0) node[node[u].next[i]].fail = 0;
else{
int v = node[u].fail;
while(v != -1){
if(node[v].next[i]){
node[node[u].next[i]].fail = node[v].next[i];
break;
}
v = node[v].fail;
}
if(v == -1) node[node[u].next[i]].fail = 0;
}
q.push(node[u].next[i]);
}
}
}
} void query(){
BigInt one;
one.set(1);
for(int i = 0; i <= m; i++){
for(int j = 0; j < size; j++){
dp[i][j].set(0);
}
}
for(int i = 0; i < tol; i++){
if(node[node[0].next[i]].cnt == 0){
dp[1][node[0].next[i]] = dp[1][node[0].next[i]] + one;
}
}
for(int i = 1; i <= m; i++){
for(int j = 0; j < size; j++){
for(int k = 0; k < tol; k++){
if(node[node[j].next[k]].cnt == 0){
dp[i + 1][node[j].next[k]] = dp[i + 1][node[j].next[k]] + dp[i][j];
}
}
}
}
BigInt ans;
ans.set(0);
for(int i = 0; i < size; i++){
if(node[i].cnt == 0){
ans = ans + dp[m][i];
}
}
ans.output();
} }ac;
char s[100];
int main(){
while(~scanf("%d%d%d", &n, &m, &p)){
scanf("%s", s);
tol = 0;
for(int i = 0; i < n; i++){
reflect[s[i]] = tol++;
}
ac.init();
while(p--){
scanf("%s", s);
ac.insert(s);
}
ac.build();
ac.query();
}
return 0;
}
POJ 1625 Censored!(AC自动机 + DP + 大数 + 拓展ASCII处理)题解的更多相关文章
- POJ 1625 Censored!(AC自动机+DP+高精度)
Censored! Time Limit: 5000MS Memory Limit: 10000K Total Submissions: 6956 Accepted: 1887 Descrip ...
- POJ1625 Censored! —— AC自动机 + DP + 大数
题目链接:https://vjudge.net/problem/POJ-1625 Censored! Time Limit: 5000MS Memory Limit: 10000K Total S ...
- POJ 1625 Censored! [AC自动机 高精度]
Censored! Time Limit: 5000MS Memory Limit: 10000K Total Submissions: 9793 Accepted: 2686 Descrip ...
- Match:Censored!(AC自动机+DP+高精度)(POJ 1625)
Censored! 题目大意:给定一些字符,将这些字符组成一个固定长度的字符串,但是字符串不能包含一些禁词,问你有多少种组合方式. 这是一道好题,既然出现了“一些”禁词,那么这题肯定和AC自动机有点 ...
- poj 1625 (AC自动机好模版,大数好模版)
题目 给n个字母,构成长度为m的串,总共有n^m种.给p个字符串,问n^m种字符串中不包含(不是子串)这p个字符串的个数. 将p个不能包含的字符串建立AC自动机,每个结点用val值来标记以当前节点为后 ...
- POJ 1625 Censored ( Trie图 && DP && 高精度 )
题意 : 给出 n 个单词组成的字符集 以及 p 个非法串,问你用字符集里面的单词构造长度为 m 的单词的方案数有多少种? 分析 :先构造出 Trie 图方便进行状态转移,这与在 POJ 2278 中 ...
- [POJ1625]Censored!(AC自动机+DP+高精度)
Censored! Time Limit: 5000MS Memory Limit: 10000K Total Submissions: 10824 Accepted: 2966 Descri ...
- 【BZOJ】4861: [Beijing2017]魔法咒语 AC自动机+DP+矩阵快速幂
[题意]给定n个原串和m个禁忌串,要求用原串集合能拼出的不含禁忌串且长度为L的串的数量.(60%)n,m<=50,L<=100.(40%)原串长度为1或2,L<=10^18. [算法 ...
- POJ1625 Censored!(AC自动机+DP)
题目问长度m不包含一些不文明单词的字符串有多少个. 依然是水水的AC自动机+DP..做完后发现居然和POJ2778是一道题,回过头来看都水水的... dp[i][j]表示长度i(在自动机转移i步)且后 ...
随机推荐
- 基于HBuilderX+UniApp+ColorUi+UniCloud 优宝库 开发实战(一)
1. 优宝库介绍 优宝库是基于阿里妈妈.淘宝联盟 淘宝商品Api,前端使用HBuilderX + UniApp + ColorUi,后端采用UniClound 精选淘宝商品进行推荐的App程序.下 ...
- 如何配置 Slf4j
一,前言 日常开发中经常需要在控制台输出一些信息,如果这些东西不加管理,那么很容易就被输出信息淹没.幸好,我们有日志相关的库来帮助我们格式化控制台的输出. 这篇文章将介绍如何配置 Slf4j 及其具体 ...
- Cisco发现协议
CDP Cisco Discovery Protocol: 思科发现协议 是一个提供关于直接相连的交换机.路由器和其它Cisco设备的综合信息的专有工具 CDP 能够发现直接相邻的设备而不管这些设备所 ...
- 一键测试VPS到国内速度脚本 SuperBench.sh,以及一键验收云主机脚本
我们买国外VPS服务器测试网络通常会用到speedtest,speedtest默认是测试到最近的节点,那么到国内速度如何呢?虽然可以指定服务器编号,但是一个个测试还是比较麻烦的,这里推荐一个脚本整合了 ...
- Java并发组件二之CyclicBarriar
使用场景: 多个线程相互等待,直到都满足条件之后,才能执行后续的操作.CyclicBarrier描述的是各个线程之间相互等待的关系. 使用步骤: 正常实例化:CyclicBarrier sCyclic ...
- IGXE搬砖项目
主要的赚钱方式和倒爷其实是差不多的,自动检测igxe平台上价格与buff相差8.5%以上的饰品,按照历史价格进行一定的过滤,防止翻车,然后自动购买. 2019年经历了十几次的改进以对抗同行的脚本,到1 ...
- SMTP 协议发送邮件的整体过程
使用 SMTP 发送邮件_使用 SMTP 发送邮件_发送邮件_用户指南_邮件推送-阿里云 https://help.aliyun.com/knowledge_detail/51622.html 通过 ...
- celery 原理
https://mp.weixin.qq.com/s/FzvZHQpF5mhV9t_HBzlcwg Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处 ...
- 洛谷 P4999
题目链接: P4999 烦人的数学作业 题目大意 详见题目 solution 有一个显而易见的结论 发现 \(ans_{l, r} = ans_{1. r} - ans_{1, l - 1}\) 那只 ...
- 存储型XSS
DVWA系列(二)存储型XSS https://www.imooc.com/article/284686 网络安全:存储型XSS https://blog.csdn.net/qq_41500251/a ...