1. 程式人生 > >字典樹Trie的簡單題目

字典樹Trie的簡單題目

題意:給N個模式串,每個不超過個字元,再給M個句子,句子長度< 100 判斷每個句子裡是否包含模式串 N < 10, M < 10 ,字元都是小寫字母
5 8
abcde
defg
cdke
ab
abcdkef
abkef
bcd
bca
add
ab
qab
f

#include<iostream>
using namespace std;
#include<vector>
#include<queue>
#define letters 26
#include<cstring>
int nNodesCount=0; struct CNode { CNode *pChilds[letters]; CNode *pPrev; //字首指標 bool bBadNode; //檢視是否是危險節點 void Init() { memset(pChilds,0,sizeof(pChilds)); bBadNode=false; pPrev=NULL; } }; CNode Tree[200]; //10個模式串,每個10個字元,每個字元一個節點, 也只要100個節點 void Insert(CNode *pRoot,char
*s) { //將模式串s插入trie樹 for (int i=0;s[i];i++) { if (pRoot->pChilds[s[i]-'a']==NULL) { pRoot->pChilds[s[i]-'a']=Tree+nNodesCount; nNodesCount++; } pRoot=pRoot-pChilds[s[i]-'a']; } pRoot->bBadNode=true; } void BuildDfa() { //在trie樹上加字首指標
for (int i=0;i<letters;i++) Tree[0]->pChilds[i]=Tree+1; Tree[0].pPrev=NULL; Tree[1].pPrev=Tree; deque<CNode *>q; q.push_back(Tree+1); while (!q.empty()) { CNode *pRoot=q.front(); q.pop_front(); for (int i=0;i<letters;i++) { CNode *p=pRoot->pChilds[i]; if (p) { CNode *pPrev=pRoot->pPrev; while (pPrev) { if (pPrev->pChilds[i]) { p->pPrev=pPrev->pChilds[i]; if (p->pPrev->bBadNode) p->bBadNode=true; //自己的pPrev指向的節點是危險節點 則自己也是危險節點 break; } else pPrev=pPrev->pPrev; } q.push_back(p); } } } } bool SearchDfa(char *s) { //返回值為true則說明包含模式串 CNode *p=Tree+1; for (int i=0;s[i];i++) { while (true) { if (p->pChilds[s[i]-'a']) { p=p->pChilds[s[i]-'a']; if (p->bBadNode) return true; break; } else p=p->pPrev; } } } int main() { nNodesCount=2; int M,N; cin>>N>>M; for (int i=0;i<N;i++) { char s[20]; cin>>s; Insert(Tree+1,s); } BuildDfa(); for (int i=0;i<M;i++) { char s[200]; cin>>s; cout<<SearchDfa(s)<<endl; } return 0; }