[POJ 1625] Censored! (AC自动机+DP+高精度)
来源:互联网 发布:淘宝电动车加热手套 编辑:程序博客网 时间:2024/05/17 02:13
链接
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;}
0 0
- POJ--1625[Censored!] AC自动机+DP+高精度
- poj 1625 Censored!(AC自动机+DP+高精度)
- poj 1625 Censored! AC自动机+dp+高精度
- [AC自动机+dp+高精度] poj 1625 Censored!
- POJ 1625 Censored! AC自动机+DP+高精度 *
- POJ 1625 Censored! (AC自动机+DP+高精度,5级)
- POJ 1625 Censored! (AC自动机 + 高精度 + DP)
- [POJ 1625] Censored! (AC自动机+DP+高精度)
- POJ 1625 Censored(AC自动机+dp)
- poj 1625 Censored! AC自动机+DP +高精度 + C艹 + java
- POJ 1625 Censored! AC自动机 简单DP 高精度
- 1625 Censored! ac自动机+dp+高精度
- POJ 1625 Censored!(自动机DP+高精度)
- poj 1625 Censored!//AC自动机+DP+大数
- POJ 1625 Censored【AC自动机+DP+大数】
- POJ 1625 Censored!(AC自动机+DP)
- 【AC自动机+DP+大数】 POJ 1625 Censored!
- POJ 1625 Censored!(AC自动机,DP)
- 76. Minimum Window Substring(贪心,滑动窗口实现,hard)
- 遍历二叉树(非递归)
- 监督式和非监督式机器学习算法
- python基础
- 做个JDBC访问MySQL的通用BaseDao
- [POJ 1625] Censored! (AC自动机+DP+高精度)
- 47. Permutations II
- CSDN-markdown编辑器语法总结
- http://www.cnblogs.com/exmyth/p/4555814.html
- XML基本语法
- 自组织网络(Ad hoc)
- python xlsxwriter创建excel图表
- poj 1088 滑雪(beta)
- uc/os II读书笔记(2)