题意:给出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. Jmeter函数助手大全

    __BeanShell 入参:BeanShell语法的程序语句或者Bean Shell脚本文件 示例: ${__BeanShell(123*456,)}:返回56088: ${__BeanShell( ...

  2. 服务之间的调用为啥不直接用 HTTP 而用 RPC?

    什么是 RPC?RPC原理是什么? 什么是 RPC? RPC(Remote Procedure Call)-远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.比 ...

  3. LOJ2436

    题目描述 幼儿园里有 N 个小朋友, lxhgww 老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果.但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于 ...

  4. 改造xxl-job的客户端日志文件生成体系

    为什么要改造XXL-JOB原有的日志文件生成体系   xxl-job原本自己的客户端日志文件生成策略是:一个日志记录就生成一个文件,也就是当数据库存在一条日志logId,对应的客户端就会生成一个文件, ...

  5. Linux命令之Crontab定时任务,利用Crontab定时执行spark任务

    Linux命令之Crontab定时任务,利用Crontab定时执行spark任务 一.Linux命令之Crontab定时任务 1.1 常见Crontab任务 1.1.1 安装crontab 1.1.2 ...

  6. SSM、SSH框架搭建,面试点总结

    文章目录 1.SSM如何搭建:三个框架的搭建: 2.SSM系统架构 3.SSM整合步骤 4.Spring,Spring MVC,MyBatis,Hibernate个人总结 5.面试资源 关于SSM.S ...

  7. Mysql,Oracle与Java字段类型映射关系

    Mysql,Oracle与Java字段类型映射关系 参考相关博文 MySQL/Oracle字段类型 Java字段类型 最大长度 BIT java.lang.Boolean 1 BLOB java.la ...

  8. Tomcat 核心组件 Container容器相关

    前言 Engine容器 Host容器 前言 Connector把封装了Request对象以及Response对象的Socket传递给了Container容器,那么在Contianer容器中又是怎么样的 ...

  9. 7.DHCP的相关命令

    1.Get-DhcpServerv4Scope :查看所有作用域状态 PS C:\Users\xinghen> Get-DhcpServerv4Scope ScopeId SubnetMask ...

  10. 设计模式(五)——原型模式(加Spring框架源码分析)

    原型模式 1 克隆羊问题 现在有一只羊 tom,姓名为: tom, 年龄为:1,颜色为:白色,请编写程序创建和 tom 羊 属性完全相同的 10 只羊. 2 传统方式解决克隆羊问题 1) 思路分析(图 ...