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步)且后 ...
随机推荐
- Navicat linux 官方最新版安装破解
我们直接去官网下载linux版navicat 下载好之后执行命令打开软件 chmod +x navicat15-premium-cs.AppImage ./navicat15-premium-cs.A ...
- 利用JavaUDPSocket+多线程模拟实现一个简单的聊天室程序
对Socket的一点个人理解:Socket原意是指插座.家家户户都有五花八门的家用电器,但它们共用统一制式的插座.这样做的好处就是将所有家用电器的通电方式统一化,不需要大费周章地在墙壁上凿洞并专门接电 ...
- WIFI 国家码和信道划分
前言 网上百度了很多资料,都没有找到国家码对应支持哪些信道的资料,无奈只能qiang到谷歌,分享给大家完整的WIFI 国家码和信道划分. 安卓WIFI国家码的影响 android中设置wifi国家码的 ...
- JMeter性能测试9:阿里云服务器压测
第一步准备好jmeter脚本 第二步 将本地的jmeter脚本上传到阿里云进行验证 检验阿里云的jmeter是否能正常运行 将本地的脚本上传到阿里云使用xshell进入到该目录下 使用命令运行刚才上传 ...
- 配置HDFS的HA
配置前准备: -- 配置hadoop -- 配置ZooKeeper,传送门:https://www.cnblogs.com/zhqin/p/11906106.html 安装配置好hadoop和ZooK ...
- Prometheus 监控之 Blackbox_exporter黑盒监测
Prometheus 监控之 Blackbox_exporter黑盒监测 1.blackbox_exporter概述 1.1 Blackbox_exporter 应用场景 2.blackbox_exp ...
- jQuery——通过Ajax发送数据
Ajax(Asynchronous JavaScript and XML,异步JavaScript和XML),一个Ajax解决方案涉及如下技术: JavaScript:处理与用户及其他浏览器相关事件的 ...
- DDD领域驱动设计:CQRS
1 前置阅读 在阅读本文章之前,你可以先阅读: DDD领域驱动设计是什么 DDD领域驱动设计:实体.值对象.聚合根 DDD领域驱动设计:仓储 MediatR一个优秀的.NET中介者框架 2 什么是CQ ...
- kafka的演进历史
首先如果我开始做一个消息队列,最开始的时候可能就是一台单机上的一个单一的log日志,不断地向这个日志中追加消息即可. 后来,可能由于一个log日志支撑不了太多的读写请求,于是就对这个log日志进行了拆 ...
- [IOI1998] Polygon (区间dp,和石子合并很相似)
题意: 给你一个多边形(可以看作n个顶点,n-1条边的图),每一条边上有一个符号(+号或者*号),这个多边形有n个顶点,每一个顶点有一个值 最初你可以把一条边删除掉,这个时候这就是一个n个顶点,n-2 ...