POJ 1625 Censored!(AC自动机->指针版+DP+大数)题解
题目:给你n个字母,p个模式串,要你写一个长度为m的串,要求这个串不能包含模式串,问你这样的串最多能写几个
思路:dp+AC自动机应该能看出来,万万没想到这题还要加大数...orz
状态转移方程dp[i + 1][j->next] += dp[i][j],其他思路和上一题hdu2457一样的,就是在AC自动机里跑就行了,不要遇到模式串结尾,然后最后把所有结尾求和就是答案。
注意下题目说给最多给50个字符且ASCII码大于32但是没说多大,直接开100多会RE,这里用map假装离散化一下。
参考:
代码:
#include<cstdio>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define ll long long
const int maxn = 1000+5;
const int maxm = 100000+5;
const int MOD = 1e7;
const int INF = 0x3f3f3f3f;
const int kind = 55;
const char baset = 0;
using namespace std;
/**********大数模板-start************/
struct BigInteger{
int A[25];
enum{MOD = 10000};
BigInteger(){memset(A, 0, sizeof(A)); A[0]=1;}
void set(int x){memset(A, 0, sizeof(A)); A[0]=1; A[1]=x;}
void print(){
printf("%d", A[A[0]]);
for (int i=A[0]-1; i>0; i--){
if (A[i]==0){printf("0000"); continue;}
for (int k=10; k*A[i]<MOD; k*=10) printf("0");
printf("%d", A[i]);
}
printf("\n");
}
int& operator [] (int p) {return A[p];}
const int& operator [] (int p) const {return A[p];}
BigInteger operator + (const BigInteger& B){
BigInteger C;
C[0]=max(A[0], B[0]);
for (int i=1; i<=C[0]; i++)
C[i]+=A[i]+B[i], C[i+1]+=C[i]/MOD, C[i]%=MOD;
if (C[C[0]+1] > 0) C[0]++;
return C;
}
bool operator == (const BigInteger& B){
for(int i = 0;i < 25;i++)
if(A[i] != B[i]) return false;
return true;
}
BigInteger operator * (const BigInteger& B){
BigInteger C;
C[0]=A[0]+B[0];
for (int i=1; i<=A[0]; i++)
for (int j=1; j<=B[0]; j++){
C[i+j-1]+=A[i]*B[j], C[i+j]+=C[i+j-1]/MOD, C[i+j-1]%=MOD;
}
if (C[C[0]] == 0) C[0]--;
return C;
}
};
/**********大数模板-end************/
struct Trie{
Trie *next[kind];
Trie *fail;
int flag;
int id;
};
Trie *root,point[maxn];
queue<Trie*> Q;
map<char,int> mp;
int head,tail,idx;
char cha[1005];
int ID(char ch){
return mp[ch];
}
Trie* NewNode(){
Trie *temp = &point[idx];
memset(temp ->next,NULL,sizeof(temp ->next));
temp ->flag = 0;
temp ->id = idx++;
temp ->fail = NULL;
return temp;
}
void Insert(char *s){
Trie *p = root;
for(int i = 0;s[i];i++){
int x = ID(s[i]);
if(p ->next[x] == NULL){
p ->next[x] = NewNode();
}
p = p ->next[x];
}
p ->flag = 1;
}
void buildFail(){
while(!Q.empty()) Q.pop();
Q.push(root);
Trie *p,*temp;
while(!Q.empty()){
temp = Q.front();
Q.pop();
for(int i = 0;i < kind;i++){
if(temp ->next[i]){
if(temp == root){
temp ->next[i] ->fail = root;
}
else{
p = temp ->fail;
while(p){
if(p ->next[i]){
temp ->next[i] ->fail = p ->next[i];
break;
}
p = p ->fail;
}
if(p == NULL) temp ->next[i] ->fail = root;
}
if(temp ->next[i] ->fail ->flag)
temp ->next[i] ->flag = 1;
Q.push(temp ->next[i]);
}
else if(temp == root)
temp ->next[i] = root;
else
temp ->next[i] = temp ->fail ->next[i];
}
}
}
BigInteger dp[55][150]; //主串第i位,AC自动机第j个
void solve(int n,int len){
BigInteger zero;
zero.set(0);
for(int i = 0;i < idx;i++)
dp[0][i].set(0);
dp[0][0].set(1);
for(int i = 1;i <= len;i++){
for(int j = 0;j < idx;j++){
if(point[j].flag) continue;
if(dp[i - 1][j] == zero) continue;
for(int k = 0;k < n;k++){
int r = point[j].next[k] ->id;
if(point[r].flag) continue;
dp[i][r] = dp[i][r] + dp[i - 1][j];
}
}
}
BigInteger ans;
ans.set(0);
for(int i = 0;i < idx;i++){
ans = ans + dp[len][i];
}
ans.print();
}
int main(){
int n,m,p,Case = 1;
while(scanf("%d%d%d",&n,&m,&p) != EOF){
idx = 0;
root = NewNode();
scanf("%s",cha);
for(int i = 0;i < n;i++){
mp[cha[i]] = i;
}
for(int i = 0;i < p;i++){
scanf("%s",cha);
Insert(cha);
}
buildFail();
solve(n,m);
}
return 0;
}
POJ 1625 Censored!(AC自动机->指针版+DP+大数)题解的更多相关文章
- POJ 1625 Censored!(AC自动机+DP+高精度)
Censored! Time Limit: 5000MS Memory Limit: 10000K Total Submissions: 6956 Accepted: 1887 Descrip ...
- poj 1625 (AC自动机好模版,大数好模版)
题目 给n个字母,构成长度为m的串,总共有n^m种.给p个字符串,问n^m种字符串中不包含(不是子串)这p个字符串的个数. 将p个不能包含的字符串建立AC自动机,每个结点用val值来标记以当前节点为后 ...
- POJ 1625 Censored! [AC自动机 高精度]
Censored! Time Limit: 5000MS Memory Limit: 10000K Total Submissions: 9793 Accepted: 2686 Descrip ...
- HDU 2825 Wireless Password(AC自动机 + 状压DP)题解
题意:m个密码串,问你长度为n的至少含有k个不同密码串的密码有几个 思路:状压一下,在build的时候处理fail的时候要用 | 把所有的后缀都加上. 代码: #include<cmath> ...
- hdu 4057--Rescue the Rabbit(AC自动机+状压DP)
题目链接 Problem Description Dr. X is a biologist, who likes rabbits very much and can do everything for ...
- hdu 2825 aC自动机+状压dp
Wireless Password Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- Match:Censored!(AC自动机+DP+高精度)(POJ 1625)
Censored! 题目大意:给定一些字符,将这些字符组成一个固定长度的字符串,但是字符串不能包含一些禁词,问你有多少种组合方式. 这是一道好题,既然出现了“一些”禁词,那么这题肯定和AC自动机有点 ...
- POJ 3691 (AC自动机+状态压缩DP)
题目链接: http://poj.org/problem?id=3691 题目大意:给定N个致病DNA片段以及一个最终DNA片段.问最终DNA片段最少修改多少个字符,使得不包含任一致病DNA. 解题 ...
- POJ 1625 Censored ( Trie图 && DP && 高精度 )
题意 : 给出 n 个单词组成的字符集 以及 p 个非法串,问你用字符集里面的单词构造长度为 m 的单词的方案数有多少种? 分析 :先构造出 Trie 图方便进行状态转移,这与在 POJ 2278 中 ...
随机推荐
- C++中的三种继承public,protected,private
( c++默认class是private继承且class内的成员默认都是private struct 默认位public 继承,struct内成员默认是public ) 三种访问权限 public: ...
- MQTT的学习研究(一)MQTT学习网站
MQTT的官方推荐网站: http://mqtt.org/software 使用IBM 的MQTT协议实现push消息地址: http://tokudu.com/2010/how-to-impleme ...
- JS-记住用户名【cookie封装引申】
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- Fluent Nhibernate Mapping for Sql Views
Views are mapped the same way tables are mapped except that you should put Readonly() in the mapping ...
- java如何使用base64生成图片文件
import org.apache.commons.codec.binary.Base64; public static void decodeFile(String base64Str,File f ...
- matplotlib 散点图scatter
最近开始学习python编程,遇到scatter函数,感觉里面的参数不知道什么意思于是查资料,最后总结如下: 1.scatter函数原型 2.其中散点的形状参数marker如下: 3.其中颜色参数c如 ...
- SpringMVC中使用@ResponseBody注解将任意POJO对象返回值转换成json进行返回
@ResponseBody 作用: 该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区. ...
- Oracle数据类型之nchar
nchar(size) nvarchar2(size) n 代表的意思是编码格式为unicode编码,无论中文或者英文都以一个字符来存放数据. 举例: 比如“a” ,占用一个字符 比如“月”,占用一 ...
- pta 习题集 5-15 数组循环左移
本题要求实现一个对数组进行循环左移的简单函数:一个数组aa中存有nn(>0>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向左移mm(≥0≥0)个位置,即将aa中的数据由(a0a ...
- htop 分析 进程对资源的消耗
[root@d ~]# htop -hhtop 2.2.0 - (C) 2004-2018 Hisham MuhammadReleased under the GNU GPL. -C --no-col ...