#include <iostream>
#include <cstring>
#include <queue>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
/*
思路:
dp[i]=sum(dp[i+len(x)])
dp[i]表示从字符i开始的字符串即后缀(s[i..L])的分解方案数。
x为是 (s[i..L]的前缀。
*/
const int MAXM=400110; //最大单词数量 * 最大单词长度
const int SIZE=26;
const int MAXN=300010;
const int MOD=20071027;
char Words[MAXN];
int F[MAXN];
struct Trie
{
int ch[MAXM][SIZE];
int val[MAXM];
int sz;
inline void init()
{
sz=1;
val[0]=0;
memset(ch[0],0,sizeof(ch[0]));
}
inline int index(char c)
{
return c-'a';
}
void insert(char* s)
{
int u=0,len=strlen(s);
for (int i=0;i<len;i++)
{
int c=index(s[i]);
if (!ch[u][c])
{
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]=len;
}
void sear(char* s,int p,int len)
{
int u=0;
for (int i=0;i<len;i++)
{
int c=index(s[i]);
if (!ch[u][c])
return;
u=ch[u][c];
if (val[u])
F[p]=(F[p]+F[p+val[u]])%MOD;
}
}
};
Trie T;
int main()
{
int s,len,cas=1;
char temp[110];
while (scanf("%s",Words)!=EOF)
{
scanf("%d",&s);
len=strlen(Words);
T.init();
F[len]=1;
for (int i=0;i<s;i++)
{
scanf("%s",temp);
T.insert(temp);
}
for (int i=len-1;i>=0;i--)
{
F[i]=0;
T.sear(Words+i,i,len-i);
}
printf("Case %d: %d\n",cas++,F[0]);
}
return 0;
}
LA 3942 Remember the Word Trie树 DP
最新推荐文章于 2021-04-14 15:04:58 发布