poj1625-AC自动机-dp-大数

题目链接:http://poj.org/problem?id=1625

Description
The alphabet of Freeland consists of exactly N letters. Each sentence of Freeland language (also known as Freish) consists of exactly M letters without word breaks. So, there exist exactly N^M different Freish sentences.
But after recent election of Mr. Grass Jr. as Freeland president some words offending him were declared unprintable and all sentences containing at least one of them were forbidden. The sentence S contains a word W if W is a substring of S i.e. exists such k >= 1 that S[k] = W[1], S[k+1] = W[2], …,S[k+len(W)-1] = W[len(W)], where k+len(W)-1 <= M and len(W) denotes length of W. Everyone who uses a forbidden sentence is to be put to jail for 10 years.
Find out how many different sentences can be used now by freelanders without risk to be put to jail for using it.

Input
The first line of the input file contains three integer numbers: N – the number of letters in Freish alphabet, M – the length of all Freish sentences and P – the number of forbidden words (1 <= N <= 50, 1 <= M <= 50, 0 <= P <= 10).
The second line contains exactly N different characters – the letters of the Freish alphabet (all with ASCII code greater than 32).
The following P lines contain forbidden words, each not longer than min(M, 10) characters, all containing only letters of Freish alphabet.

Output
Output the only integer number – the number of different sentences freelanders can safely use.

Sample Input
2 3 1
ab
bb

Sample Output
5

题意
给出n个字符,p个违规串,问有多少长度为m的串不包含违规串。

思路
AC自动机加dp,同时转移时数据过大要大数。dp[i][j]记录长度为i时,第i位在AC自动机上编号为j的点时的方案数。转移方程dp[i+1][AC[j][k]]+=dp[i][j]。最后取dp[m][0到AC自动机编号上限]的和。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int mod = 1e8;
struct node {
int len;
int a[15];
void operator +=(const node &x) {
int p = 0;
for (int i = 0; i <= len || i <= x.len; i++) {
int c = p + a[i] + x.a[i];
a[i] = c % mod;
p = c / mod;
}
len = max(len, x.len);
if (p)
a[++len] = p;
}
void print() {
printf("%d", a[len]);
for (int i = len - 1; i >= 0; i--)
printf("%08d", a[i]);
cout << endl;
}
};
int n, m, p;
struct Trie {
int AC[105][55];
int fail[105];
int numend[105];
node dp[55][105];
int mp[256];
int len;
int root;
int newcode() {
memset(AC[len], 0, sizeof(AC[len]));
numend[len++] = 0;
return len - 1;
}
void init() {
memset(mp, 0, sizeof(mp));
memset(dp, 0, sizeof(dp));
dp[0][0].a[0] = 1;
len = 0;
root = newcode();
}
void idx(string s) {
int len = s.length();
for (int i = 0; i < len; i++)
mp[s[i]] = i;
}
void build(string s) {
int len = s.length();
int now = root;
for (int i = 0; i < len; i++) {
if (!AC[now][mp[s[i]]]) {
AC[now][mp[s[i]]] = newcode();
}
now = AC[now][mp[s[i]]];
}
numend[now] = 1;
}
void get_fail() {
queue<int>q;
for (int d = 0; d < n; d++)
if (AC[root][d]) {
fail[AC[root][d]] = root;
q.push(AC[root][d]);
}
else
AC[root][d] = root;
while (!q.empty()) {
int now = q.front();
q.pop();
numend[now] |= numend[fail[now]];
for (int d = 0; d < n; d++) {
if (!AC[now][d]) {
AC[now][d] = AC[fail[now]][d];
continue;
}
fail[AC[now][d]] = AC[fail[now]][d];
q.push(AC[now][d]);
}
}
}
void slove() {
for (int i = 0; i < m; i++)
for (int j = 0; j < len; j++)
if (!numend[j])
for (int k = 0; k < n; k++) {
if (!numend[AC[j][k]])
dp[i + 1][AC[j][k]]+= dp[i][j];
}
node ans;
memset(ans.a, 0, sizeof(ans.a));
ans.len = 0;
for (int j = 0; j < len; j++)
ans += dp[m][j];
ans.print();
}
}ac;
string s;
int main() {
while (scanf("%d%d%d", &n, &m, &p) != EOF) {
ac.init();
cin >> s;
ac.idx(s);
for (int i = 0; i < p; i++) {
cin >> s;
ac.build(s);
}
ac.get_fail();
ac.slove();
}
}

谢谢你请我吃糖果

你可能感兴趣的:(poj1625-AC自动机-dp-大数)