#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;
}
}
Trie图模板 数据结构与算法实习
猜你喜欢
转载自blog.csdn.net/weixin_41087003/article/details/103700315
今日推荐
周排行