题目: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; }