题目:给你n个字母,p个模式串,要你写一个长度为m的串,要求这个串不能包含模式串,问你这样的串最多能写几个

思路:dp+AC自动机应该能看出来,万万没想到这题还要加大数...orz

状态转移方程dp[i + 1][j->next] += dp[i][j],其他思路和上一题hdu2457一样的,就是在AC自动机里跑就行了,不要遇到模式串结尾,然后最后把所有结尾求和就是答案。

注意下题目说给最多给50个字符且ASCII码大于32但是没说多大,直接开100多会RE,这里用map假装离散化一下。

参考:

C++大数模板 BigInteger

代码:

#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;elsetemp ->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+大数)题解相关推荐

  1. POJ - 1625 Censored!(AC自动机+dp+高精度运算)

    题目链接:点击查看 题目大意:给出一个含有 n 个不同字符的字符集,接着规定所有单词的长度为 m ,再给出 k 个病毒串,问有多少个字符串中不含有病毒串 题目分析:这个题目和之前做过的DNA的那个题有 ...

  2. Censored! POJ - 1625(AC自动机 + dp +高精度模板)

    题目链接 题目大意:给你一个字母表,给定一些敏感字符串,问长度为m且不含任意敏感字符串的串有多少个.(字符全部来自字母表) 思路:首先第一个坑点是输入的字符是unsigned char,可能出现负的A ...

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

    题目链接:Censored! 解析:AC自动机 + 高精度 + 简单DP. 字符有可能会超过128,用map映射一下即可. 中间的数太大,得上高精度. 用矩阵快速幂会超时,简单的DP就能解决时间的问题 ...

  4. poj-1625 Censored![ac自动机+dp+高精度]

    题目地址 先把病毒串丢进ac自动机里面. dp[i][j]表示长度为i的从trie图的根节点到j满足条件的串的数量. 因为答案很大,要用到高精度. 注意的是建图的时候,ed[u] |= ed[f[u] ...

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

    链接 POJ 1625 题意 给出P个模式串,问长度为M且不含有P中任何一个为子串的字符串有多少种. 给出了大小为N的一个字符集,属于ASCII但不一定为英文字母. 最终答案不进行取模,所以可能非常大 ...

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

    题意 : 给出 n 个单词组成的字符集 以及 p 个非法串,问你用字符集里面的单词构造长度为 m 的单词的方案数有多少种? 分析 : 与 POJ 2778 非常相似的一道题目,如果没有做过就尝试去了解 ...

  7. HDU - 2825 Wireless Password(AC自动机+状压dp)

    题目链接:点击查看 题目大意:给出 m 个匹配串,问长度为 n 的字符串中,至少包含 k 个匹配串(可重叠)的字符串有多少个 题目分析:考虑到n,m,k都特别小,所以可以先用AC自动机将状态关系转移出 ...

  8. 【hdu2825】ac自动机 + 状压dp

    传送门 题目大意: 给你一些密码片段字符串,让你求长度为n,且至少包含k个不同密码片段串的字符串的数量. 题解: 因为密码串不多,可以考虑状态压缩 设dp[i][j][sta]表示长为i的字符串匹配到 ...

  9. POJ - 1625 Censored!

    希望自己能成为日更博主 题目连接:http://poj.org/problem?id=1625  题目大意:给你n个字母,再给你p个字符串,问有多少个长度为m的只由给出的n个字母构成的字符串,且字符串 ...

最新文章

  1. linux 脚本 lang,golang可以编写shell脚本吗
  2. mysql丢失召回_mysql笔记
  3. linux——vim命令详细说明
  4. c# async/await编程
  5. ubuntu samba服务器的安装文件,在Ubuntu16.04中搭建samba服务器并用win10连接实现共享文件...
  6. 读书笔记:软件人才-管理的艺术
  7. python软件是什么原因引起的_Python对程序员重要的原因在哪里?
  8. 东风本田4S店违规收取续保押金 ,电台主持在线怒怼经理,反被指无教养?
  9. 给Lisp程序员的Python简介
  10. 独家揭秘!抖音爆款实时视频漫画变身特效背后技术
  11. 简单易懂的snmpd.conf配置文件说明
  12. php获取手机品牌,9 大国产手机品牌相机水印大比拼,哪款才是你的最爱?
  13. 如何去实现机械灵巧手玩魔方和弹钢琴_单手解魔方效果惊艳,OpenAI发布最强机器手...
  14. 一文带你了解Java编程语言的前世今生 | Java核心知识点整理
  15. 数据库系统概论思维导图
  16. matlab画图入门教程
  17. CS 61A Spring 2019 HW01 学习笔记
  18. VC编译生成asm文件设置
  19. 真是其了怪的jwplayer
  20. oracle 正版识别,正版Oracle产品价格

热门文章

  1. Presto Cannot write to non-managed Hive table
  2. 项目轮播图功能实现和导航栏的实现
  3. Linux命令之火车来了
  4. 工业机器人的应用有哪些
  5. android 接电话 返回后黑屏,安卓手机打电话黑屏原因和解决方法
  6. Apollo星火计划学习笔记——第六讲上自动驾驶感知基础(I)
  7. Android网络开发
  8. 向上沟通:你必须要注意的三个误区
  9. python股票分析入门_学习用Python分析股票数据(入门)
  10. 【退役贴】再见了ACM,再会了算法竞赛