题目链接:https://vjudge.net/problem/POJ-1625

 

Censored!
Time Limit: 5000MS   Memory Limit: 10000K
Total Submissions: 10870   Accepted: 2979

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

Source

Northeastern Europe 2001, Northern Subregion

 

题意:

给出p个单词,求长度为m且不含有已给单词的字符串有多少个?其中字母表有n个字母。

 

题解:

POJ2278 DNA Sequence无异,只不过此题没有取模,而答案可能很大,所以用到高精度。而且字符串长度较小,可以直接用动态规划进行求解,而不需要用到矩阵进行加速。

 

代码如下:

POJ1625 Censored!  —— AC自动机 + DP + 大数_i++POJ1625 Censored!  —— AC自动机 + DP + 大数_i++_02
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <vector>
  6 #include <cmath>
  7 #include <queue>
  8 #include <stack>
  9 #include <map>
 10 #include <string>
 11 #include <set>
 12 using namespace std;
 13 typedef long long LL;
 14 const double EPS = 1e-6;
 15 const int INF = 2e9;
 16 const LL LNF = 9e18;
 17 const int MOD = 1e5;
 18 const int MAXN = 50*50+10;
 19 
 20 struct BigInt
 21 {
 22     const static int mod = 10000;
 23     const static int DLEN = 4;
 24     int a[100],len;
 25     BigInt()
 26     {
 27         memset(a,0,sizeof(a));
 28         len = 1;
 29     }
 30     BigInt(int v)
 31     {
 32         memset(a,0,sizeof(a));
 33         len = 0;
 34         do
 35         {
 36             a[len++] = v%mod;
 37             v /= mod;
 38         }while(v);
 39     }
 40     BigInt operator +(const BigInt &b)const
 41     {
 42         BigInt res;
 43         res.len = max(len,b.len);
 44         for(int i = 0;i <= res.len;i++)
 45             res.a[i] = 0;
 46         for(int i = 0;i < res.len;i++)
 47         {
 48             res.a[i] += ((i < len)?a[i]:0)+((i < b.len)?b.a[i]:0);
 49             res.a[i+1] += res.a[i]/mod;
 50             res.a[i] %= mod;
 51         }
 52         if(res.a[res.len] > 0)res.len++;
 53         return res;
 54     }
 55     void output()
 56     {
 57         printf("%d",a[len-1]);
 58         for(int i = len-2;i >=0 ;i--)
 59             printf("%04d",a[i]);
 60         printf("\n");
 61     }
 62 };
 63 
 64 BigInt dp[2][MAXN];
 65 int M[128];
 66 struct Trie
 67 {
 68     int sz, base;
 69     int next[MAXN][50], fail[MAXN], end[MAXN];
 70     int root, L;
 71     int newnode()
 72     {
 73         for(int i = 0; i<sz; i++)
 74             next[L][i] = -1;
 75         end[L++] = false;
 76         return L-1;
 77     }
 78 
 79     void init(int _sz, int _base)
 80     {
 81         sz = _sz;
 82         base = _base;
 83         L = 0;
 84         root = newnode();
 85     }
 86     void insert(char buf[])
 87     {
 88         int len = strlen(buf);
 89         int now = root;
 90         for(int i = 0; i<len; i++)
 91         {
 92             if(next[now][M[buf[i]]] == -1) next[now][M[buf[i]]] = newnode();
 93             now = next[now][M[buf[i]]];
 94         }
 95         end[now] |= true;
 96     }
 97     void build()
 98     {
 99         queue<int>Q;
100         fail[root] = root;
101         for(int i = 0; i<sz; i++)
102         {
103             if(next[root][i] == -1) next[root][i] = root;
104             else fail[next[root][i]] = root, Q.push(next[root][i]);
105         }
106         while(!Q.empty())
107         {
108             int now = Q.front();
109             Q.pop();
110             end[now] |= end[fail[now]];
111             for(int i = 0; i<sz; i++)
112             {
113                 if(next[now][i] == -1) next[now][i] = next[fail[now]][i];
114                 else fail[next[now][i]] = next[fail[now]][i], Q.push(next[now][i]);
115             }
116         }
117     }
118 
119     void query(int len)
120     {
121         for(int i = 0; i<=1; i++)
122         for(int j = 0; j<L; j++)
123             dp[i][j] = 0;
124 
125         int cur = 0;
126         dp[cur][root] = 1;
127         for(int i = 0; i<len; i++)
128         {
129             for(int j = 0; j<L; j++)
130                 dp[cur^1][j] = 0;
131             for(int j = 0; j<L; j++)
132             {
133                 if(end[j]) continue;
134                 for(int k = 0; k<sz; k++)
135                 {
136                     if(end[next[j][k]]) continue;
137                     dp[cur^1][next[j][k]] = dp[cur^1][next[j][k]] + dp[cur][j];
138                 }
139             }
140             cur ^= 1;
141         }
142 
143         BigInt ret = 0;
144         for(int i = 0; i<L; i++)
145             ret = ret + dp[cur][i];
146         ret.output();
147     }
148 };
149 
150 Trie ac;
151 char buf[MAXN];
152 int main()
153 {
154     int n, m, p;
155     while(scanf("%d%d%d", &n,&m,&p)!=EOF)
156     {
157         ac.init(n, 0);
158         scanf("%s", buf);
159         for(int i = 0; buf[i]; i++)
160             M[buf[i]] = i;
161         for(int i = 1; i<=p; i++)
162         {
163             scanf("%s", buf);
164             ac.insert(buf);
165         }
166         ac.build();
167         ac.query(m);
168     }
169 }
View Code