链接

POJ 1625


题意

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


题解

给出模式串找不含其中任何一个的串的种类数,这类的题目大多可以用trie图+矩阵快速幂解决。但是这道题目的答案不取模,显然要用高精度,如果用在矩阵快速幂中套用高精度。。。感觉即使不MLT也TLT了,所以这里要使用dp。
从dp的角度看,这道题目的转移很简单,dp[i][j]代表长度为i,位于自动机j节点满足题意的种类数,显然根据trie图很好转移。

感觉trick在于,char类型变量事实上是带符号的类型,所以直接作为数组下标会越界,加上一个基值就可以了。
大整数类感觉mod不要用10了,用10000比较好,节省空间,提高速度。


代码

#include <cstdio>
#include <fstream>
#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
typedef unsigned char uchar;
#define MAX_L (111)
#define degree (55)
int tsf[1<<9], cnt;
int trieG[MAX_L][MAX_L];
struct Aho
{int next[MAX_L][degree], nd[MAX_L], fail[MAX_L];int root, L;int newnode(){for(int i = 0; i < degree; i++)next[L][i] = -1;nd[L] = 0;return L++;}void init(){L = 0;root = newnode();}void insert(char s[]){//printf("insert\n");int now = root;for(int i = 0, key, sz = strlen(s); i < sz; i++){key = tsf[256 + s[i]];if(next[now][key] == -1)next[now][key] = newnode();now = next[now][key];}nd[now] = 1;}void build(){//printf("build\n");queue<int> que;fail[root] = root;for(int i = 0; i < degree; i++)if(next[root][i] == -1)next[root][i] = root;else{fail[next[root][i]] = root;que.push(next[root][i]);}while(!que.empty()){//printf("while\n");int now = que.front();que.pop();if(nd[fail[now]])nd[now] = 1;for(int i = 0; i < degree; i++)if(next[now][i] == -1)next[now][i] = next[fail[now]][i];else{fail[next[now][i]] = next[fail[now]][i];que.push(next[now][i]);}}//printf("build end\n");}void gettrieG(int n){//printf("getG\n");memset(trieG, 0, sizeof(trieG));for(int i = 0; i < L; i++)for(int j = 0; j < n; j++)if(!nd[next[i][j]]) trieG[i][next[i][j]]++;}
} actree;
struct bign
{#define MAX_B (100)#define MOD (10000)int a[MAX_B], n;bign() { a[0] = 0, n = 1; }bign(int num){n = 0;do {a[n++] = num % MOD;num /= MOD;} while(num);}bign& operator= (int num){ return *this = bign(num); }bign operator+ (const bign& b) const{bign c = bign();int cn = max(n, b.n), d = 0;for(int i = 0, x, y; i < cn; i++){x = (n > i) ? a[i] : 0;y = (b.n > i) ? b.a[i] : 0;c.a[i] = (x + y + d) % MOD;d = (x + y + d) / MOD;}if(d) c.a[cn++] = d;c.n = cn;return c;}bign& operator+= (const bign& b){*this = *this + b;return *this;}bign operator* (const bign& b) const{bign c = bign();int cn = n + b.n, d = 0;for(int i = 0; i <= cn; i++)c.a[i] = 0;for(int i = 0; i < n; i++)for(int j = 0; j < b.n; j++){c.a[i + j] += a[i] * b.a[j];c.a[i + j + 1] += c.a[i + j] / MOD;c.a[i + j] %= MOD;}while(cn > 0 && !c.a[cn-1]) cn--;if(!cn) cn++;c.n = cn;return c;}friend ostream& operator<< (ostream& _cout, const bign& num){printf("%d", num.a[num.n - 1]);for(int i = num.n - 2; i >= 0; i--)printf("%04d", num.a[i]);return _cout;}
};
#define MAX_M (55)
bign dp[MAX_M][MAX_L];
int main()
{int N, M, P;char table[100];while(cin >> N >> M >> P){scanf("%s", table);for(int i = 0; i < N; i++)tsf[256 + table[i]] = i;actree.init();for(int i = 0; i < P; i++){scanf("%s", table);actree.insert(table);}actree.build();actree.gettrieG(N);for(int i = 0; i <= M; i++)for(int j = 0; j < actree.L; j++){dp[i][j] = bign();}dp[0][0] = 1;for(int i = 0; i < M; i++)for(int j = 0; j < actree.L; j++)for(int k = 0; k < actree.L; k++) {dp[i + 1][k] += dp[i][j] * bign(trieG[j][k]);}bign ans = bign();for(int i = 0; i < actree.L; i++)ans += dp[M][i];cout << ans << endl;}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+高精度]

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

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

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

  5. Censored! :ac自动机 + DP

    分析 如果字符串的长度大一点可以用矩阵快速幂来做,因为数据范围比较小,可以用DP来代替 我们去枚举每一位在a自动机中的位置,再去枚举下一位的位置,判断是否打过标记,然后进行状态转移 需要注意的是,如果 ...

  6. uvalive4842(AC自动机+DP)

    题意: 给出猴子打字时打某个字母的概率,猴子最多可以敲键盘m次,问得到的长度是m的单词包含模式串的概率. 思路: AC自动机+dp. 首先,我们用模式串构造一个AC自动机,用dp[i]][j]表示当前 ...

  7. HDU 2296 Ring AC自动机 + DP

    题意:给你n个模式串,每个模式串有一个得分,让你构造出一个长度为N之内且分数最高的文本串;输出字典序列最小的. 解题思路:  AC自动机 + DP , 不过要输出字典序列最小,多开一个 一个三维字符串 ...

  8. bzoj 1030: [JSOI2007]文本生成器(AC自动机+DP)

    1030: [JSOI2007]文本生成器 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 5187  Solved: 2136 [Submit][St ...

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

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

最新文章

  1. Apache JMeter2.13 实战
  2. LVS Nginx HAProxy 三种负载均衡优缺点比较
  3. android oppo调试模式,OPPO A59 开启USB调试模式
  4. idea安装golang插件(仅针对2017年之前的idea版本)
  5. 【剑指offer】面试题43:n个骰子的点数
  6. SparkSQL中UDAF案例分析
  7. HDnoip2017题解
  8. 找出出现次数最多的字母
  9. android 刷新标题栏,Android 自定义标题栏的实例详解
  10. 数据结构与算法之三直接插入排序
  11. 单片机的各种存储的含义和区别
  12. 【BZOJ2164】采矿 树链剖分+线段树维护DP
  13. 编程菜鸟的日记-初学尝试编程递归
  14. Dropdownlist插入值!
  15. 顺丰快递:请签收MySQL灵魂十连问
  16. 台式计算机睡眠时间是什么意思,电脑电源选项中的睡眠和休眠各是什么意思,什么作用?...
  17. oracle发生20001,ORA-20001错误一例
  18. 抽象类可用于创建对象吗_蜈蚣兰,见过吗?可用于口腔炎,鼻窦炎,气管炎,肾盂肾炎...
  19. npm 安装碰到SSL问题
  20. 2048小游戏源代码

热门文章

  1. maximo数据集列表关联其他表字段
  2. 为什么大数据工程师比Java程序员工资高50%?
  3. gcc:扩展功能:除标准里定义的C特性之外的功能;-pedantic
  4. JVM - 垃圾回收(垃圾标记阶段算法,内存泄漏与溢出)(2)
  5. vue keep-alive用法
  6. 查找同一网络的计算机,怎么从网络中查询另一台计算机的ip地址
  7. Django中models模型(操作数据库)
  8. 解决Win2016提示“发生身份验证错误 要求的函数不受支持”的问题
  9. influxdb的percentile函数
  10. css table thead tr border生效