POJ 1625 Censored! (AC自动机+DP+大数加法)
来源:互联网 发布:js test函数 编辑:程序博客网 时间:2024/05/18 00:29
题目大意
- 给出包含N个字符的字典,组成长度为M的句子,求无禁止单词的句子有多少个。禁止单词有P个,单词长度不超过10,所以字符的ASCII码均大于32(1 <= N <= 50, 1 <= M <= 50, 0 <= P <= 10)。
分析
- 状态dp[i][j]表示第i步时,到达状态j的字符串数,途中不能经过危险结点
则状态转移方程为
dp[i][j] = sum(dp[i-1][k]),其中j是k的后继状态
很明显,所以结果加起来超过long long。所以需要用到大数的加法
- 构造AC自动机时,失败结点为危险的结点也要变成危险结点。
- 输入字符的ASCII码可能超过128,所以需要用的映射,不然RE
代码
#include <iostream>#include <cstring>#include <queue>#include <cstdio>#include <algorithm>using namespace std;const int maxn = 110;const int N = 51;const int sigma_size = 50;const int M = 100;struct AC { int ch[maxn][sigma_size]; int val[maxn]; int sz; char s[N]; int idx(char c) { int L = 0 , R = strlen(s) - 1; while(L <= R) { int M = (L + R) / 2; if(c == s[M]) return M; if(c > s[M]) L = M + 1; else R = M - 1; } return L; } void init() { sz=1; val[0]=0; cin >> s; int len = strlen(s); sort(s , s + len); memset(ch[0],0,sizeof(ch[0])); } void insert(string const &s , int v) { int cur = 0 , len = s.length(); for(int i = 0; i < len; i++) { int u = idx(s[i]); if(!ch[cur][u]) { memset(ch[sz] , 0 , sizeof(ch[sz])); val[sz] = 0; ch[cur][u] = sz++; } cur = ch[cur][u]; } val[cur] = v; } int f[maxn]; void getfail() { queue<int> Q; f[0] = 0; for(int i = 0; i < sigma_size; i++) { int v = ch[0][i]; if(v) {f[v] = 0; Q.push(v);} } while(!Q.empty()) { int cur = Q.front(); Q.pop(); for(int i = 0; i < sigma_size; i++){ int u = ch[cur][i]; if(!u) {ch[cur][i] = ch[f[cur]][i]; continue;} Q.push(u); int j = f[cur]; while(j && !ch[j][i]) j = f[j]; f[u] = ch[j][i]; if(val[ch[j][i]]) val[u] = 1; } } } void ADD(int *A , int *B) //大数加法A=A+B { int len1 = 0 , len2 = 0; for(int i = M-1; i >= 0; i--) if(A[i]) {len1 = i; break;} for(int i = M-1; i >= 0; i--) if(B[i]) {len2 = i; break;} int len = max(len1 , len2); for(int i = 0; i <= len; i++) { A[i] += B[i]; A[i+1] += A[i] / 10; A[i] %= 10; } } int dp[N][maxn][M]; //dp[i][j]表示第i步时,到达状态j的字符串数 void DP(int m , int n) { memset(dp , 0 , sizeof(dp)); dp[0][0][0] = 1; for(int i = 1; i <= m; i++) for(int j = 0; j < sz; j++) { if(val[j]) continue; for(int k = 0; k < n; k++) { int cur = ch[j][idx(s[k])]; if(val[cur]) continue; ADD(dp[i][cur] , dp[i-1][j]); } } int ans[M] = {0} , len = 0; for(int i = 0; i < sz; i++) if(!val[i]) ADD(ans , dp[m][i]); for(int i = M-1; i >= 0; i--) if(ans[i]) {len = i; break;} for(int i = len; i >= 0; i--) cout << ans[i]; cout << endl; }};AC ac;int main(){ //cout << sizeof(ac.dp) / 1024 << endl; int n , m , p; while(cin >> n >> m >> p) { getchar(); ac.init(); for(int i = 1; i <= p; i++) { string str; cin >> str; ac.insert(str , i); } ac.getfail(); ac.DP(m , n); }}
数据
50 50 10
qwertyuiop[]\asdfghjkl;’zxcvbnm,./QWERTYUIOP{}|AS
aegaegu
etoijqt
tquqi
witowwt
zxcjnc
oeit
potieq
iojge
nvoq
piqper
88816479228348672447914159817057714124274948616722531360571673747292358424682407
6329032 50 10
、¥ウЖ┆q忏溴骁栝觌祉铒?
Β
驿?
馥?
癌ē?
く.?
く.铽
Β‘飒
ウq憝?
驿Γ飒
隘ルΒ°?
1721978265757417133897998525905218434633371225724869729302087935758854628748
0 0
- POJ 1625 Censored! (AC自动机+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)
- poj 1625 Censored! 【AC自动机 + DP + 强力大数模版】
- poj--1625Censored!+AC自动机上的dp+大数
- HDU 1625 Censored! (AC自动机 + 大数 + dp)
- POJ--1625[Censored!] AC自动机+DP+高精度
- POJ 1625 Censored!(AC自动机+DP)
- poj 1625 Censored!(AC自动机+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+高精度 *
- POJ 1625 Censored!(AC自动机+DP)
- 惠普测试需求管理解决方案(惠普应用生命管理周期(ALM))实训任务1
- php的整数类型及转换
- Leetcode96: Spiral Matrix
- 用lsof查看进程打开的文件情况
- escape()、encodeURI()、encodeURIComponent()区别详解
- POJ 1625 Censored! (AC自动机+DP+大数加法)
- 利用JNotify和EHCache实现静态文件缓存
- HDU2029 Palindromes _easy version
- Alena's Schedule(模拟)
- Sql Server 分页查询
- background-position 用法详细介绍
- 【Python】Learn Python the hard way, ex39 字典操作
- linux中shell变量$#,$@,$0,$1,$2的含义解释
- Clojure 文档翻译--概述及类库导入