题目粘贴不过来
样例
abcd
4
a
b
cd
ab
abcd=a+b+cd;abcd=ab+cd;
答案就是两种 题目就是问你 给你一个串能被下面的串有几种方式组成
我们怎么考虑这个问题呢?我们对下面所有字符串建一个Trie图 那么设置dp
dp[i]就是从i开始到结束存在多少种方式 那么dp[i+j+1]如果存在cnt[now] (i+j<len) 那么后面的也是一种可行的方式
所以进行dp累加即可
/*
UVA 1401
*/
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
#include <set>
using namespace std;
#define dbg(x) ;
const int MAX_N = 310024;
const int MOD = 20071027;
long long dp[MAX_N];
int tree[MAX_N][26],cnt[MAX_N];
int tot,root;
int newnode(){
for(int i = 0;i<26;++i)
tree[tot][i] =-1;
cnt[tot++] = 0;
return tot-1;
}
void init(){
tot = 0;
root =newnode();
}
void Insert(string str){
int now = root;
int len = str.length();
for(int i= 0;i<len;++i){
if(tree[now][str[i]-'a']==-1) tree[now][str[i]-'a'] = newnode();
now = tree[now][str[i]-'a'];
}
cnt[now]++;
dbg(now);
}
int query(string str){
int len = str.length();
int now = root;
int ans = 0;
for(int i = 0;i<len;++i){
if(tree[now][str[i]-'a']==-1) return 0;
now = tree[now][str[i]-'a'];
ans += cnt[now];
}
return ans;
}
int main(){
string s,str;
int Case = 0;
while(cin >> s){
Case++ ;
memset(dp,0,sizeof(dp));
int n;
cin >> n;
init();
for(int i = 1;i<=n;++i){
cin >> str;
Insert(str);
}
int len = s.length();
dp[len] = 1;
for(int i = len-1;i>=0;i--){
int now = 0;
for(int j = 0;j+i<len;j++){
dbg(str[i+j]-'a');
dbg(tree[now][s[i+j]-'a']);
if(tree[now][s[i+j]-'a']==-1){
break;
}
now = tree[now][s[i+j]-'a'];
dbg(cnt[now]);
dbg(now);
if(cnt[now]){
dbg(dp[i]);
dbg(dp[i+j+1]);
dp[i] = (dp[i]+dp[i+j+1])%MOD;
}
}
}
cout<<"Case "<<Case<<": "<<dp[0] << endl;
}
return 0;
}