利用Trie树进行转移
#include<cstdio>
#include<cstring>
#define MAXN 400003
#define SN 26
#define MAXL 300003
#define MOD 20071027
using namespace std;
struct Trie {
Trie *s[SN];
bool end;
void clear() {
memset(s, 0, sizeof(s));
end=false;
}
}trie[MAXN];
char str[MAXL], tmp[103];
int n, tot, dp[MAXL];
void insert() {
Trie *cur=&trie[0];
for(int i=0; tmp[i]; ++i) {
int p=tmp[i]-'a';
if(!cur->s[p]) {
trie[tot].clear();
cur->s[p]=&trie[tot++];
}
cur=cur->s[p];
}
cur->end=true;
}
int l;
void chk(int add,int jmp) {
Trie *cur=&trie[0];
for(int i=jmp;i<=l;i++){
if(cur->s[str[i]-'a']){
cur=cur->s[str[i]-'a'];
if(cur->end)
dp[i]=(dp[i]+add)%MOD;
}
else break;
}
}
int main() {
for(int cas=1; scanf("%s",&str[1])!=EOF; ++cas) {
scanf("%d", &n);
trie[0].clear();
tot=1;
for(int i=0; i<n; ++i) {
scanf("%s", tmp);
insert();
}
memset(dp, 0, sizeof(dp));
dp[0]=1;
l=strlen(&str[1]); //dp[i]表示由所给字符串组成(1~i)部分的源串的方法数
for(int i=1; i<=l; ++i) {
if(dp[i-1])
chk(dp[i-1],i); //这里迭代是由dp[i-1]根据源串推导dp[j](i=<j<=l)
}
printf("Case %d: %d\n", cas, dp[l]);
}
return 0;
}