题意:给出一个由S个不同的单词组成的字典和一个长字符串,把这个字符串分解成若干个单词的连接单词可以重复使用,有多少种方法?(PS 应该%20071027,白书写错了)
分析:dp + trie tree.
#include <cstdio>
#include <cstring>
#include <iostream>
#define maxnode 400001
#define MAXN 20071027
using namespace std;
int n,number;
long long dp[300005];
char S[300005],tmp[105];
struct trie
{
int ch[maxnode][26];
int val[maxnode];
int tot,num;
void build()
{
num = 0;
tot = 1;
memset(ch[0],0,sizeof(ch[0]));
}
int idx(char c)
{
return c - 'a';
}
void insert(char s[])
{
int u = 0,n = strlen(s);
for(int i = 0;i < n;i++)
{
int c = idx(s[i]);
if(!ch[u][c])
{
memset(ch[tot],0,sizeof(ch[tot]));
val[tot] = 0;
ch[u][c] = tot++;
}
u = ch[u][c];
}
if(val[u] == 0) val[u] = ++num;
}
void find(char s[],int pos)
{
int u = 0,n = min(100,int (strlen(s)));
for(int i = 0;i < n;i++)
{
int c = idx(s[i]);
if(!ch[u][c]) break;
u = ch[u][c];
if(val[u]) dp[pos] = (dp[pos] + dp[pos + i + 1]) % MAXN;
}
}
} tree;
int main()
{
while(~scanf("%s",S))
{
tree.build();
scanf("%d",&n);
for(int i = 1;i <= n;i++)
{
scanf("%s",tmp);
tree.insert(tmp);
}
memset(dp,0,sizeof(dp));
int l = strlen(S);
dp[l] = 1;
for(int i = l - 1;i >= 0;i--) tree.find(S + i,i);
cout<<"Case "<<++number<<": "<<dp[0]<<endl;
}
}