题目:BZOJ1212、洛谷P2292。
题目大意:给你n个单词和m篇文章,如果一篇文章的前k个字符能分成若干个单词,那么就认为这k个字符能被理解,求每篇文章最多能被理解几个字符。
解题思路:由于单词长度最大为10,我们建一棵Trie,用c[i]表示前i个字符能否被理解,枚举i,然后从i往后扩展即可。有点类似dp的思想,具体见代码注释。
找了半天的错发现c数组没清空也是没谁了╮(╯▽╰)╭
C++ Code:
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,ans;
char s[1000005];
bool c[1000005];//c[i]表示文章0~i能否被理解
struct trie{
bool exist;
trie* nxt[26];
trie():exist(false){
for(int i=0;i<26;++i)nxt[i]=NULL;
}
}*d;
int main(){
d=new trie;
scanf("%d%d",&n,&m);
while(n--){//构造字典树
scanf("%s",s);
trie* p=d;
for(int i=0;s[i];++i){
int v=s[i]-'a';
if(p->nxt[v]==NULL)p->nxt[v]=new trie;
p=p->nxt[v];
}
p->exist=true;
}
while(m--){//枚举单词开始的节点
scanf("%s",s);
ans=0;
memset(c,0,sizeof(c));
for(int i=0;s[i];++i)
if(i==0||c[i-1]){//当i为0或前面的文章能被理解时才能继续
trie* p=d;
for(int l=1;l<=10;++l){//枚举单词长度
if(!s[i+l-1])break;//超过s直接跳出
p=p->nxt[s[i+l-1]-'a'];
if(p==NULL)break;//不存在这个前缀时直接退出
if(p->exist){//成功理解
c[i+l-1]=true;
if(ans<i+l)ans=i+l;
}
}
}
printf("%d
",ans);
}
return 0;
}