题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=22109
解法:我们写出递推方程d[i]=sum[d[i+len(x)],d[i] 表示以i开始的字符粗的分解方案数。对于这个我们以算出他的复杂度n*m,n为单词个数,m为查找的复杂度。当我们把单词存在数组遍历时,复杂度为m(4000*100)。这个会超时的。由于这里用到了前缀,我们可以用trie来优化。
关于字典树:字典树可以用来处理前缀相关的问题,用来优化字符查询和统计的问题。查询一个单词的复杂度为这个词的长度。我们用数组ch【i】【j】来表示节点i的为j的字母的位置。然后我们就可以来构造字典树,一般用数组来写,这样调试方便。多组输入的不要忘记初始化!!!
代码如下:
#include<algorithm>
#include<iostream>
#include<cmath>
#include<map>
#include<string.h>
#include<cstring>
#include<vector>
#include<queue>
#include<stdio.h>
using namespace std;
#define ll long long int
#define maxn 400008
int len[maxn],cnt_len,d[maxn],ed;
char s[maxn],sc[maxn];
const int mod=20071027;
#include<iostream>
#include<cmath>
#include<map>
#include<string.h>
#include<cstring>
#include<vector>
#include<queue>
#include<stdio.h>
using namespace std;
#define ll long long int
#define maxn 400008
int len[maxn],cnt_len,d[maxn],ed;
char s[maxn],sc[maxn];
const int mod=20071027;
struct trie
{
public:
int ch[maxn][30];
int val[maxn];
int sz=1;
void tt() { sz=1; memset(ch[0],0,sizeof(ch[0]) ); };
int idx(char c) { return c-'a'; }
{
public:
int ch[maxn][30];
int val[maxn];
int sz=1;
void tt() { sz=1; memset(ch[0],0,sizeof(ch[0]) ); };
int idx(char c) { return c-'a'; }
void insert_(char *s2,int v)
{
int u=0,n=strlen(s2);
for(int i=0;i<n;i++)
{
int c=idx(s2[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;
};
void search_(char *s1)
{
int u=0,n=strlen(s1);
for(int i=0;i<n;i++)
{
int c=idx(s1[i]);
if(!ch[u][c])
return ;
u=ch[u][c];
if(val[u])
{
len[cnt_len++]=i+1;
}
}
}
}t;
int main(void)
{
//freopen("in.txt","r",stdin);
int pvis,dd;
pvis=0;
while(scanf("%s",s)!=EOF)
{
t.tt();
memset(len,0,sizeof(len));
memset(d,0,sizeof(d));
ed=cnt_len=0;
int n=strlen(s);
scanf("%d",&dd);
for(int i=0;i<dd;i++)
{
scanf("%s",sc);
t.insert_(sc,1);
}
for(int i=n-1;i>=0;i--)
{
cnt_len=0;
t.search_(s+i);
d[n]=1;
for(int j=0;j<cnt_len;j++)
{
d[i]=(d[i]+d[i+len[j]])%mod;
}
{
int u=0,n=strlen(s2);
for(int i=0;i<n;i++)
{
int c=idx(s2[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;
};
void search_(char *s1)
{
int u=0,n=strlen(s1);
for(int i=0;i<n;i++)
{
int c=idx(s1[i]);
if(!ch[u][c])
return ;
u=ch[u][c];
if(val[u])
{
len[cnt_len++]=i+1;
}
}
}
}t;
int main(void)
{
//freopen("in.txt","r",stdin);
int pvis,dd;
pvis=0;
while(scanf("%s",s)!=EOF)
{
t.tt();
memset(len,0,sizeof(len));
memset(d,0,sizeof(d));
ed=cnt_len=0;
int n=strlen(s);
scanf("%d",&dd);
for(int i=0;i<dd;i++)
{
scanf("%s",sc);
t.insert_(sc,1);
}
for(int i=n-1;i>=0;i--)
{
cnt_len=0;
t.search_(s+i);
d[n]=1;
for(int j=0;j<cnt_len;j++)
{
d[i]=(d[i]+d[i+len[j]])%mod;
}
}
printf("Case %d: %d\n",++pvis,d[0]);
}
}