Trie图入门题

来源:互联网 发布:淘宝小钱包 编辑:程序博客网 时间:2024/04/28 11:43
题目: 
给N个模式串,每个不超过个字符,再给M个句子,句子长度<
100 判断每个句子里是否包含模式串
 N < 10, M < 10 ,字符都是小写字母
5 8
abcde
defg
cdke
ab
f
abcdkef
abkef
bcd
bca
add
ab
qab

f

#include<iostream>#include<cstdio>#include<cstring>#include<queue>#include<algorithm>using namespace std;const int maxn=100+5;const int letters=26; int nNode;struct CNode{CNode *pChilds[letters];CNode *pPrev;bool bBadNode;void Init(){memset(pChilds,0,sizeof(pChilds));bBadNode=false;pPrev=NULL;}}tree[200];void BuildDfa(){for(int i=0;i<letters;i++)tree[0].pChilds[i]=tree+1;tree[1].pPrev=tree;tree[0].pPrev=NULL;queue<CNode*> Q;Q.push(tree+1);while(!Q.empty()){CNode *root=Q.front(); Q.pop();for(int i=0;i<letters;i++){CNode *p=root->pChilds[i];if(p==NULL) continue;CNode *pPrev=root->pPrev;while(pPrev){if(pPrev->pChilds[i]!=NULL){p->pPrev=pPrev->pChilds[i];if(p->pPrev->bBadNode)p->bBadNode=true;break;  //只要找一次后缀节点就好了,因为建dfa是一层一层来的,上一层肯定已经好了 }else pPrev=pPrev->pPrev;   }Q.push(p);}}}bool SearchDfa(char *s){CNode *p=tree+1;for(int i=0;s[i];i++){for(;;){if(p->pChilds[s[i]-'a']!=NULL){p=p->pChilds[s[i]-'a'];if(p->bBadNode) return true;  //遇到危险节点或者终止节点就表明找到了 break;}else p=p->pPrev;  //到前驱节点 }}return false;}void Insert(CNode *root,char *s){for(int i=0;s[i];i++){if(root->pChilds[s[i]-'a']==NULL)root->pChilds[s[i]-'a']=tree+nNode++;root=root->pChilds[s[i]-'a'];}root->bBadNode=true;}int main(){int N,M;cin>>N>>M;nNode=2;  //0作为空指针,1为根指针 char s[200];for(int i=0;i<N;i++){scanf("%s",s);Insert(tree+1,s);}BuildDfa();for(int i=0;i<M;i++){scanf("%s",s);cout<<SearchDfa(s)<<endl;}return 0;}


0 0