题意:

给出一n种字符的字典,有p个禁用的单词,

问能组成多少个不同的长度为m的合法字符串。(m<=50)

题解:

是不是个我们之前做的题目非常非常像,题意都一样。

直接将上次写的AC自动机+矩阵快速幂的代码交上去。

然后突然发现没有取模,好像直接炸了。即便只有50,但是方案数还是爆__int128了

处理不了,这题还是必须用大数的。

p<=10 我们可以考虑状压实现。

这题还是和之前的题目有点关系的,需要求出可达矩阵,然后根据这个去DP

dp[i][j] 表示第 i 步 在AC自动机 j 这个节点 的方案数目,

然后第 i 步只跟 第 i - 1步的状态有关,然后可以滚动掉这一维。

不用试不滚动的了,会mle的。 别问我怎么知道的!!!!

 #include <set>
#include <map>
#include <stack>
#include <queue>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <time.h>
#include <cstring>
#include <iostream>
#include <algorithm> #define pi acos(-1.0)
#define eps 1e-9
#define fi first
#define se second
#define rtl rt<<1
#define rtr rt<<1|1
#define bug printf("******\n")
#define mem(a, b) memset(a,b,sizeof(a))
#define name2str(x) #x
#define fuck(x) cout<<#x" = "<<x<<endl
#define sf(n) scanf("%d", &n)
#define sff(a, b) scanf("%d %d", &a, &b)
#define sfff(a, b, c) scanf("%d %d %d", &a, &b, &c)
#define sffff(a, b, c, d) scanf("%d %d %d %d", &a, &b, &c, &d)
#define pf printf
#define FIN freopen("../date.txt","r",stdin)
#define gcd(a, b) __gcd(a,b)
#define lowbit(x) x&-x
#define IO iOS::sync_with_stdio(false) using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int maxn = 1e6 + ;
const int maxm = 8e6 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ; struct Matrix {
int mat[][], n; Matrix() {} Matrix(int _n) {
n = _n;
for (int i = ; i < n; i++)
for (int j = ; j < n; j++)
mat[i][j] = ;
} Matrix operator*(const Matrix &b) const {
Matrix ret = Matrix(n);
for (int i = ; i < n; i++)
for (int j = ; j < n; j++)
for (int k = ; k < n; k++) {
int tmp = (long long) mat[i][k] * b.mat[k][j] % mod;
ret.mat[i][j] = (ret.mat[i][j] + tmp) % mod;
}
return ret;
}
}; char buf[];
int n, m, p;
map<char, int> mp; struct Aho_Corasick {
int next[][], fail[], End[];
int root, cnt; int newnode() {
for (int i = ; i < ; i++) next[cnt][i] = -;
End[cnt++] = ;
return cnt - ;
} void init() {
cnt = ;
root = newnode();
} void insert(char buf[]) {
int len = strlen(buf);
int now = root;
for (int i = ; i < len; i++) {
if (next[now][mp[buf[i]]] == -) next[now][mp[buf[i]]] = newnode();
now = next[now][mp[buf[i]]];
}
End[now]++;
} void build() {
queue<int> Q;
fail[root] = root;
for (int i = ; i < ; i++)
if (next[root][i] == -) next[root][i] = root;
else {
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
while (!Q.empty()) {
int now = Q.front();
Q.pop();
if (End[fail[now]]) End[now] = ;
for (int i = ; i < ; i++)
if (next[now][i] == -) next[now][i] = next[fail[now]][i];
else {
fail[next[now][i]] = next[fail[now]][i];
Q.push(next[now][i]);
}
}
} Matrix get_Matrix() {
Matrix ret = Matrix(cnt);
for (int i = ; i < cnt; ++i) {
for (int j = ; j < n; ++j) {
if (!End[next[i][j]]) ret.mat[i][next[i][j]]++;
}
}
return ret;
} void debug() {
for (int i = ; i < cnt; i++) {
printf("id = %3d,fail = %3d,end = %3d,chi = [", i, fail[i], End[i]);
for (int j = ; j < ; j++) printf("%2d", next[i][j]);
printf("]\n");
}
}
} ac; const int MAXL = ;
const int MAXN = ;
const int DLEN = ; class Big {
public:
int a[], len; Big(const int b = ) {
int c, d = b;
len = ;
memset(a, , sizeof(a));
while (d > MAXN) {
c = d - (d / (MAXN + )) * (MAXN + );
d = d / (MAXN + );
a[len++] = c;
}
a[len++] = d;
} Big(const char *s) {
int t, k, index, L;
memset(a, , sizeof(a));
L = strlen(s);
len = L / DLEN;
if (L % DLEN) len++;
index = ;
for (int i = L - ; i >= ; i -= DLEN) {
t = ;
k = i - DLEN + ;
if (k < ) k = ;
for (int j = k; j <= i; j++) t = t * + s[j] - '';
a[index++] = t;
}
} Big operator/(const LL &b) const {
Big ret;
LL down = ;
for (int i = len - ; i >= ; i--) {
ret.a[i] = (a[i] + down * (MAXN + )) / b;
down = a[i] + down * (MAXN + ) - ret.a[i] * b;
}
ret.len = len;
while (ret.a[ret.len - ] == && ret.len > ) ret.len--;
return ret;
} bool operator>(const Big &T) const {
int ln;
if (len > T.len) return true;
else if (len == T.len) {
ln = len - ;
while (a[ln] == T.a[ln] && ln >= ) ln--;
if (ln >= && a[ln] > T.a[ln]) return true;
else return false;
} else return false;
} Big operator+(const Big &T) const {
Big t(*this);
int big = T.len > len ? T.len : len;
for (int i = ; i < big; i++) {
t.a[i] += T.a[i];
if (t.a[i] > MAXN) {
t.a[i + ]++;
t.a[i] -= MAXN + ;
}
}
if (t.a[big] != ) t.len = big + ;
else t.len = big;
return t;
} Big operator-(const Big &T) const {
int big;
bool flag;
Big t1, t2;
if (*this > T) {
t1 = *this;
t2 = T;
flag = ;
} else {
t1 = T;
t2 = *this;
flag = ;
}
big = t1.len;
for (int i = ; i < big; i++) {
if (t1.a[i] < t2.a[i]) {
int j = i + ;
while (t1.a[j] == ) j++;
t1.a[j--]--;
while (j > i) t1.a[j--] += MAXN;
t1.a[i] += MAXN + - t2.a[i];
} else t1.a[i] -= t2.a[i];
}
t1.len = big;
while (t1.a[t1.len - ] == && t1.len > ) {
t1.len--;
big--;
}
if (flag) t1.a[big - ] = - t1.a[big - ];
return t1;
} LL operator%(const int &b) const {
LL d = ;
for (int i = len - ; i >= ; i--) d = ((d * (MAXN + )) % b + a[i]) % b;
return d;
} Big operator*(const Big &T) const {
Big ret;
int i, j, up, temp, temp1;
for (i = ; i < len; i++) {
up = ;
for (j = ; j < T.len; j++) {
temp = a[i] * T.a[j] + ret.a[i + j] + up;
if (temp > MAXN) {
temp1 = temp - temp / (MAXN + ) * (MAXN + );
up = temp / (MAXN + );
ret.a[i + j] = temp1;
} else {
up = ;
ret.a[i + j] = temp;
}
}
if (up != ) ret.a[i + j] = up;
}
ret.len = i + j;
while (ret.a[ret.len - ] == && ret.len > ) ret.len--;
return ret;
} void print() {
printf("%d", a[len - ]);
for (int i = len - ; i >= ; i--) printf("%04d", a[i]);
}
}; Big dp[][]; int main() {
//FIN;
while (~scanf("%d%d%d", &n, &m, &p)) {
mp.clear();
scanf("%s", buf);
int len = strlen(buf);
for (int i = ; i < len; ++i) mp[buf[i]] = i;
ac.init();
for (int i = ; i < p; ++i) {
scanf("%s", buf);
ac.insert(buf);
}
ac.build();
Matrix mat = ac.get_Matrix();
// for (int i = 0; i < mat.n; ++i) {
// for (int j = 0; j < mat.n; ++j) {
// printf("%d ",mat.mat[i][j]);
// }
// printf("\n");
// }
int now=;
dp[now][] = ;
for (int i = ; i < mat.n; ++i) dp[now][i] = ;
for (int i = ; i <= m; ++i) {
now^=;
for (int j = ; j < mat.n; ++j) dp[now][j]=;
for (int j = ; j < mat.n; ++j) {
for (int k = ; k < mat.n; ++k) {
if (mat.mat[j][k]) dp[now][k] = dp[now][k] + dp[now^][j] * mat.mat[j][k];
}
}
}
Big ans = ;
for (int i = ; i < mat.n; ++i) ans = ans + dp[now][i];
ans.print();
printf("\n");
}
return ;
}

Censored! POJ - 1625 AC自动机+大数DP的更多相关文章

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

    题目大意:首先给一个字符集合,这个集合有N个字符,然后需要一个长度为M的句子,但是据子里面不能包含的串有P个,每个串里面的字符都是有字符集和里面的字符构成的,现在想知道最多能构造多少个不重复的句子. ...

  2. 【HDU3530】 [Sdoi2014]数数 (AC自动机+数位DP)

    3530: [Sdoi2014]数数 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 682  Solved: 364 Description 我们称一 ...

  3. 关于AC自动机和DP的联系

    首先是描述个大概.不说一些特殊的DP 或者借用矩阵来状态转移 (这些本质都是一样的). 只讲AC自动机和DP的关系(个人理解). AC自动机 又可以叫做状态机. 我一开始的认为.AC 自动机提供了一些 ...

  4. 【bzoj3530】[Sdoi2014]数数 AC自动机+数位dp

    题目描述 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串.例如当S=(22,333,0233)时,233是幸运数,2333.20233.3223不是幸运 ...

  5. BZOJ 3530 [SDOI2014]数数 (Trie图/AC自动机+数位DP)

    题目大意:略 裸的AC自动机+数位DP吧... 定义f[i][x][0/1]表示已经匹配到了第i位,当前位置是x,0表示没到上限,1到上限,此时数是数量 然而会出现虚拟前导零,即前几位没有数字的情况, ...

  6. POJ 3691 (AC自动机+状态压缩DP)

    题目链接:  http://poj.org/problem?id=3691 题目大意:给定N个致病DNA片段以及一个最终DNA片段.问最终DNA片段最少修改多少个字符,使得不包含任一致病DNA. 解题 ...

  7. POJ2778&HDU2243&POJ1625(AC自动机+矩阵/DP)

    POJ2778 题意:只有四种字符的字符串(A, C, T and G),有M中字符串不能出现,为长度为n的字符串可以有多少种. 题解:在字符串上有L中状态,所以就有L*A(字符个数)中状态转移.这里 ...

  8. POJ 2778 (AC自动机+矩阵乘法)

    POJ 2778 DNA Sequence Problem : 给m个只含有(A,G,C,T)的模式串(m <= 10, len <=10), 询问所有长度为n的只含有(A,G,C,T)的 ...

  9. 【POJ2778】DNA Sequence(AC自动机,DP)

    题意: 生物课上我们学到,DNA序列中只有A, C, T和G四种片段. 经科学发现,DNA序列中,包含某些片段会产生不好的基因,如片段"ATC"是不好片段,则"AGATC ...

随机推荐

  1. bzoj1015题解

    [题意分析] 给你一张无向图,要求支持删点和询问连通块数. [解题思路] 可以直接可持久化并查集大力艹过去. 考虑到正着删点就是倒着加点,所以并不需要可持久化.复杂度O((k+m)α(n)). [参考 ...

  2. 1 visual studio code 配置C++开发环境 (windows 开发环境)

    0 引言 最近帮GF(不幸变成ex了)配置C++开发环境,一开始想给她装个visual studio13完事,但是一想到自己安装以及使用时的诸多麻烦,就有点退却,觉得没有这个必要.正好了解到vscod ...

  3. NX二次开发-UFUN获取工程图所有视图tag UF_DRAW_ask_views

    #include <uf.h> #include <uf_draw.h> #include <uf_drf.h> #include <uf_obj.h> ...

  4. GO语言range的用法 (2013-08-09 14:08:26)

    range是go语言系统定义的一个函数. 函数的含义是在一个数组中遍历每一个值,返回该值的下标值和此处的实际值. 假如说a[0]=10,则遍历到a[0]的时候返回值为0,10两个值. 下面是一个例子: ...

  5. Python实现二叉堆

    Python实现二叉堆 二叉堆是一种特殊的堆,二叉堆是完全二元树(二叉树)或者是近似完全二元树(二叉树).二叉堆有两种:最大堆和最小堆.最大堆:父结点的键值总是大于或等于任何一个子节点的键值:最小堆: ...

  6. Python3 From Zero——{最初的意识:004~迭代器和生成器}

    一.反向迭代:reversed() >>> a [1, 2, 3, 4] >>> for x in reversed(a): ... print(x, end=' ...

  7. js用document.getElementById时要注意!

    <!DOCTYPE html> <html lang="en"> <head> <script src="http://code ...

  8. 23-Ubuntu-文件和目录命令-查看文件内容-more 和 cat

    1. more---适合查看内容多的文件 格式: more 文件名 操作键 功能 空格键 显示手册页下一屏 Enter键 一次滚动手册页的一行 b 返回上一屏 f 前滚一屏 q 退出 例: more ...

  9. 树形结构_红黑树:平衡2X 哈夫曼树:最优2X

    红黑树:平衡2X 哈夫曼树:最优2X 红黑树 :TreeSet.TreeMap 哈夫曼树 1. 将w1.w2.…,wn看成是有n 棵树的森林(每棵树仅有一个结点): 2. 在森林中选出根结点的权值最小 ...

  10. 不同JDK版本之间的intern()方法的区别-JDK6 VS JDK6+

    String s = new Stirng(“a”); s.intern(); JDK6:当调用intern()方法时,如果字符串常量池先前已创建出该字符串对象,则返回池中的该字符串的引用.否则,将此 ...