您的位置:首页 > 其它

UVALive - 3942:Remember the Word

2017-11-26 12:22 323 查看
发现字典里面的单词数目多且长度短,可以用字典树保存

f[i]表示s[i~L]的分割方式,则有f[i]=∑f[i+len(word[j])] 其中word[j]为s[i~L]的前缀

注意字典树又叫前缀树,所以用前缀更方便,否则按顺序dp的话就要把字符倒序了

复杂度O(L*l) L为字符串长度,l为单词长度

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define MAXN 300005
#define MOD 20071027
using namespace std;
struct Trie{
Trie* nxt[26];
int v;
Trie(){
for(int i=0;i<26;i++){
nxt[i]=NULL;
}
v=0;
}
};
Trie *root;
void insert(char s[],int vl){
Trie *p=root;
int len=strlen(s);
for(int i=0;i<len;i++){
int t=s[i]-97;
if(p->nxt[t]){
p=p->nxt[t];
}
else{
p->nxt[t]=new Trie;
p=p->nxt[t];
}
}
p->v=vl;
}
int f[MAXN];
char s[MAXN];
int n,L;
int find(int st){
int ret=0;
Trie *p=root;
for(int i=st;i<L;i++){
int t=s[i]-97;
if(p->nxt[t]){
p=p->nxt[t];
if(p->v){
(ret+=f[i+1])%=MOD;
}
}
else{
return ret;
}
}
return ret;
}
void del(Trie *p){
if(p){
for(int i=0;i<26;i++){
if(p->nxt[i]){
del(p->nxt[i]);
}
}
delete p;
}
}
int main()
{
int T=0;
while(~scanf("%s",s)){
memset(f,0,sizeof(f));
del(root);
L=strlen(s);
root=new Trie;
scanf("%d",&n);
for(int i=1;i<=n;i++){
char ch[105]={0};
scanf("%s",ch);
insert(ch,1);
}
f[L]=1;
for(int i=L-1;i>=0;i--){
f[i]=find(i);
}
printf("Case %d: %d\n",++T,f[0]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: