前缀树 就是字典树 学了个不是链表的字典树 白皮书上的模版
求一个字符串有几种表示方法
dp[i+j]=dp[i+j]+dp[i] 递推把 如果制酒遍历4000个子串 会超时 然后用字典树 最多比较100次就行
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxnode = 4010*100;
const int sigma_size = 26;
const int MAXN = 300010;
const int MOD = 20071027;
char str[MAXN];
int dp[MAXN];
struct trie
{
int ch[maxnode][sigma_size];
int val[maxnode];
int sz;
void init()
{
sz = 1;
memset(ch[0],0,sizeof(ch[0]));
}
int idx(char c)
{
return c - 'a';
}
void insert(char *s,int v)
{
int u = 0,n = strlen(s);
for(int i = 0; i < n; i++)
{
int c = idx(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] = v;
}
}Trie;
int main()
{
char a[110];
int cas = 0,n,i,j;
while(scanf("%s",str+1)!=EOF)
{
Trie.init();
memset(dp,0,sizeof(dp));
scanf("%d",&n);
while(n--)
{
scanf("%s",a);
Trie.insert(a,1);
}
n = strlen(str + 1);
dp[0] = 1;
str[0] = 'a';
for(i = 0; str[i]; i++)
{
int u = 0;
for(j = 1;j <= n; j++)
{
int c = Trie.idx(str[i+j]);
u = Trie.ch[u][c];
if(!u)
break;
if(Trie.val[u] == 1)
{
dp[i+j] += dp[i];
dp[i+j] %= MOD;
}
}
}
printf("Case %d: ",++cas);
printf("%d\n",dp[n]);
}
return 0;
}