题意:给出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处理)题解的更多相关文章

  1. POJ 1625 Censored!(AC自动机+DP+高精度)

    Censored! Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 6956   Accepted: 1887 Descrip ...

  2. POJ1625 Censored! —— AC自动机 + DP + 大数

    题目链接:https://vjudge.net/problem/POJ-1625 Censored! Time Limit: 5000MS   Memory Limit: 10000K Total S ...

  3. POJ 1625 Censored! [AC自动机 高精度]

    Censored! Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 9793   Accepted: 2686 Descrip ...

  4. Match:Censored!(AC自动机+DP+高精度)(POJ 1625)

     Censored! 题目大意:给定一些字符,将这些字符组成一个固定长度的字符串,但是字符串不能包含一些禁词,问你有多少种组合方式. 这是一道好题,既然出现了“一些”禁词,那么这题肯定和AC自动机有点 ...

  5. poj 1625 (AC自动机好模版,大数好模版)

    题目 给n个字母,构成长度为m的串,总共有n^m种.给p个字符串,问n^m种字符串中不包含(不是子串)这p个字符串的个数. 将p个不能包含的字符串建立AC自动机,每个结点用val值来标记以当前节点为后 ...

  6. POJ 1625 Censored ( Trie图 && DP && 高精度 )

    题意 : 给出 n 个单词组成的字符集 以及 p 个非法串,问你用字符集里面的单词构造长度为 m 的单词的方案数有多少种? 分析 :先构造出 Trie 图方便进行状态转移,这与在 POJ 2278 中 ...

  7. [POJ1625]Censored!(AC自动机+DP+高精度)

    Censored! Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 10824   Accepted: 2966 Descri ...

  8. 【BZOJ】4861: [Beijing2017]魔法咒语 AC自动机+DP+矩阵快速幂

    [题意]给定n个原串和m个禁忌串,要求用原串集合能拼出的不含禁忌串且长度为L的串的数量.(60%)n,m<=50,L<=100.(40%)原串长度为1或2,L<=10^18. [算法 ...

  9. POJ1625 Censored!(AC自动机+DP)

    题目问长度m不包含一些不文明单词的字符串有多少个. 依然是水水的AC自动机+DP..做完后发现居然和POJ2778是一道题,回过头来看都水水的... dp[i][j]表示长度i(在自动机转移i步)且后 ...

随机推荐

  1. Redis 实战 —— 04. Redis 数据结构常用命令简介

    字符串 P39 Redis 的字符串是一个有字节组成的序列,可以存储以下 3 种类型的值:字节串(byte string).整数.浮点数. 在需要的时候, Redis 会将整数转换成浮点数.整数的取值 ...

  2. Mac中安装Git

    Mac 安装git 打开Mac终端输入git命令 如果出现以下代码说明已经安装 usage: git [--version] [--help] [-C <path>] [-c <na ...

  3. 关于Mysql数据库建库字符集utf8mb4下,排序规则utf8mb4_bin和utf8mb4_general_ci选择造成的查询匹配大小写问题

    场景描述: 项目采用了分库模式进行不同业务的开发,在共有的功能模块进行设计的时候采用主从库,或者各分库之中存在同样的库表结构,在使用过程中做库表同步的时候一定要保证库表所在的数据库的字符集和编码格式是 ...

  4. 30分钟带你理解 Raft 算法

    为什么需要 Raft? Raft 是什么? Raft 的目标 前置条件:复制状态机 Raft 基础 Leader 选举(选举安全特性) 日志复制(Leader只附加.日志匹配) 安全 学习资料 使用 ...

  5. ArchLinux安装后所需要的环境和工具

    ArchLinux安装后所需要的环境和工具 工具: Dolphin 文件管理器 ntfs-3G 移动硬盘挂载 octopi 实时检查更新 KDE Connect 手机电脑远程连接 DBeaver Co ...

  6. Connection reset by peer的常见原因及解决办法 RST 大文件上传

    Connection reset by peer的常见原因及解决办法 Connection reset by peer的常见原因 - 简书 https://www.jianshu.com/p/263e ...

  7. memset 在c++中使用细节注意

    C语言,在利用struct进行数据封装时,经常会使用memset(this,0,sizeof(*this))来初始化.而C++中,有时候也会用到struct,在利用memset进行初始化时,非常容易踩 ...

  8. 自己动手实现java断点/单步调试(一)

    又是好长时间没有写博客了,今天我们就来谈一下java程序的断点调试.写这篇主题的主要原因是身边的公司或者个人都执着于做apaas平台,简单来说apaas平台就是一个零代码或者低代码的配置平台,通过配置 ...

  9. Spring Boot 核心配置文件 bootstrap & application

    Spring Boot 核心配置文件 bootstrap & application 1.SpringBoot bootstrap配置文件不生效问题 2.bootstrap/ applicat ...

  10. 并发编程(Process对象的join方法)(

    一. Process对象的join方法 在主进程运行过程中如果想并发地执行其他的任务,我们可以开启子进程,此时主进程的任务与子进程的任务分两种情况 情况一:在主进程的任务与子进程的任务彼此独立的情况下 ...