题目大意:首先给一个字符集合,这个集合有N个字符,然后需要一个长度为M的句子,但是据子里面不能包含的串有P个,每个串里面的字符都是有字符集和里面的字符构成的,现在想知道最多能构造多少个不重复的句子。
分析:跟以前做过的那两题差不多,不过这个不让取余....不过考虑到字符长度也不大,最多也就50,所以使用一般的dp也可以。ps.在做高高精度运算的时候输出答案竟然正着输出了....然后就一直WA....确实有些时间没有敲过高精度题目了。
代码如下:
==============================================================================================================================
#include<iostream> #include<algorithm> #include<stdio.h> #include<string.h> #include<queue> using namespace std; const int MAXN = 107; const int oo = 1e9+7; char WordList[MAXN]; int MaxSon, Matrix[MAXN][MAXN]; struct Ac_Trie { int next[MAXN][MAXN], size; int Fail[MAXN], End[MAXN], root; int newnode() { memset(next[size], -1, sizeof(next[size])); Fail[size] = End[size] = false; return size++; } void InIt() { size = 0; root = newnode(); } void Insert(char s[]) { int now = root; for(int i=0; s[i]; i++) { int k = strchr(WordList, s[i]) - WordList; if(next[now][k] == -1) next[now][k] = newnode(); now = next[now][k]; } End[now] = true; } void GetFail() { queue<int> Q; int now = root; Fail[root] = root; for(int i=0; i<MaxSon; i++) { if(next[now][i] == -1) next[now][i] = root; else { Fail[next[now][i]] = root; Q.push(next[now][i]); } } while(Q.size()) { now = Q.front(); Q.pop(); for(int i=0; i<MaxSon; i++) { if(next[now][i] == -1) next[now][i] = next[Fail[now]][i]; else { Fail[next[now][i]] = next[Fail[now]][i]; Q.push(next[now][i]); } } End[now] |= End[Fail[now]]; } } void GetMatrix() { memset(Matrix, false, sizeof(Matrix)); for(int i=0; i<size; i++) for(int k=0; k<MaxSon; k++) { if(!End[next[i][k]] && !End[i]) Matrix[i][next[i][k]] += 1; } } }; Ac_Trie ac; void BigNumAdd(int a[], int num, int b[]) { for(int i=0; i<MAXN; i++) b[i] += a[i] * num; for(int i=0; i<MAXN-1; i++) { b[i+1] += b[i] / 10; b[i] %= 10; } } int main() { int N, P; while(scanf("%d%d%d", &MaxSon, &N, &P) != EOF) { char s[MAXN]; ac.InIt(); getchar(); gets(WordList); while(P--) { gets(s); ac.Insert(s); } ac.GetFail(); ac.GetMatrix(); int dp[2][MAXN][MAXN] = {0}, op=0; dp[1][0][0] = 1; while(N--) { memset(dp[op], false, sizeof(dp[op])); for(int i=0; i<ac.size; i++) for(int j=0; j<ac.size; j++) { if(Matrix[i][j]) {///dp[op][j] += dp[op^1][i] * Matrix[i][j]; BigNumAdd(dp[op^1][i], Matrix[i][j], dp[op][j]); } } op ^= 1; } int ans[MAXN] = {0}; for(int i=0; i<ac.size; i++) BigNumAdd(dp[op^1][i], 1, ans); N = MAXN - 1; while(ans[N] == 0 && N > 0) N--; for(int i=N; i>=0; i--) printf("%d", ans[i]); printf(" "); } return 0; }