Trie图模板 数据结构与算法实习

在这里插入图片描述

#include <iostream>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;
#define MAXL 50000
#define LETTERS 26
int node_count;
/*危险节点的概念:
1) 终止节点是危险节点
2) 如果一个节点的前缀指针指向危险节点,那么它也是危险节点*/
struct node {
	 bool danger;//是否是危险节点
	 node* prev;//前缀指针
	 node* child[LETTERS];//子节点
	 node() {
		  memset(child, 0, sizeof(child));
		  prev = NULL;
		  danger = false;
	 }
};
node Lis[MAXL];//存储
/*初始化Lis[0]和Lis[1],使得Lis[0]所有子节点都是Lis[1]且所有对前缀指针的回溯都到达Lis[0]为止*/
void init() {
 for (int i = 0; i < LETTERS; i++) {
  Lis[0].child[i] = Lis + 1;
 }
 Lis[0].prev = NULL;
 Lis[1].prev = Lis;
}
/*插入模式串建立trie树*/
void insert(char* s) {
 node* ptr = Lis + 1;
 for (int i = 0; s[i]; i++) {
  if (ptr->child[(s[i] - 'a')] == NULL) {//若trie图中没有这个节点就创造一个
   ptr->child[(s[i] - 'a')] = Lis + node_count;
   node_count++;//总节点数加一
  }
  ptr = ptr->child[(s[i] - 'a')];
 }
 ptr->danger = true;
}
/*在trie树中插入前缀指针得到trie图*/
void Build_Tree(){
	 init();
	 queue<node*> Line;//使用队列来完成按层次建立前缀指针的目的
	 Line.push(Lis + 1);
	 while (!Line.empty()) {
	  node* p = Line.front();
	  Line.pop();
	  for (int i = 0; i < LETTERS; i++) {//对所有非空子节点求其prev和danger
	   node* pchild = p->child[i];
	   node* pprev = p->prev;//用于前缀回溯,先指向父节点的前缀指针
	   if (pchild) {//非空
	    node* tmp = pprev->child[i];//非空即有这条路径说明找到了最近的前缀指针
	    while (!tmp) {
	     pprev = pprev->prev;//不断回溯,可能最终回溯到Lis处。此时tmp将必然变为Lis+1
	     tmp = pprev->child[i];
	    }
	    pchild->prev = tmp;//找到该节点的前缀指针
	    if (tmp->danger) {//判断是否危险
	     pchild->danger = true;
	    }
	    Line.push(pchild);//入队将来再构建该节点的子节点的prev和danger
	   }
	  }
	 }
}
/*对目标串s进行遍历确定是否有模式串存在,存在返回true*/
bool Search(char* s) {
 node* p = Lis + 1;
 for (int i = 0; s[i]; i++) {
  while(p->child[(s[i] - 'a')] == NULL) {
   p = p->prev;//失败就回溯到前缀指针
  }
  p = p->child[(s[i] - 'a')];
  if (p->danger) {
   return true;
  }
 }
 return false;
}
int main()
{ 
	 node_count = 2;
	 char str[MAXL];
	 int m, n; cin >> m;
	 for (int i = 0; i < m; i++){
	  cin >> str;
	  insert(str);
	 }
	 Build_Tree();
	 cin >> n;
	 for (int i = 0; i < n; i++) {
		  cin >> str;
		  bool f=Search(str);
		  if (f) 
		   cout << "YES" << endl;
		  else 
		   cout << "NO" << endl;
		  
	}
}
发布了8 篇原创文章 · 获赞 1 · 访问量 112

猜你喜欢

转载自blog.csdn.net/weixin_41087003/article/details/103700315