hiho刷题日记——第四天Trie图

用和kmp相似的思路,将trie树变为trie图。以用于在长篇文章中查找是否存在字典中的单词。

在此强调本文中的‘根’和一般的树中的‘根’不一样!


1.建立trie树

①建立一个结点结构体和初始化函数

typedef struct node{
bool isEnd;//结点是否为单词的结尾
struct node* trie;//结点的根(这里的根和一般的树的根不一样,但是怎么解释呢。不知道啊。)
struct node* next[26];
}TrieNode; 

void initNode(TrieNode *p)
{
p->isEnd = 0;
for(int i=0;i<26;i++)
p->next[i]=NULL;
}

一个head结点并初始化。

③建立一个headTrie结点作为head的根,并将其所有的next指向head。

对于输入单词的处理:

输入一个字符串并扫描,只要还没结束:

并判断是否存在对应字符的子结点。

若存在,转到子结点;否者建一个子结点并转到该结点。

当单词扫描结束时,将最后一个结点的isEnd属性标为true。

void makeTrie(char *w)
{
int i=0;
TrieNode* p=&head;

while(w[i])
{
if(p->next[w[i]-97])
{
p=p->next[w[i]-97];
}
else
{
TrieNode *q=(TrieNode *)malloc(sizeof(TrieNode));
initNode(q);
p->next[w[i]-97]=q;
p=q;
}
i++;
}
p->isEnd=1;
}

2.建立trie图

用广度遍历。将&head加入遍历队列,并将head.trie赋值为&headTrie作为head的根。

只要遍历队列里还有元素,则做一下操作:

①先取出元素。

②判断是否存在对应字符的子结点。

若有,则将其子结点加入遍历队列,并将其子结点的根结点设为其根结点的对应字符的子结点。。。。。文字好绕,上代码p->next[i]->trie=p->trie->next[i];

若无,则将其对应的子结点设为其根结点的对应字符的子结点。p->next[i]=p->trie->next[i];

这里就是用的kmp的思想。

void makeTrieMap()
{
int front=0,rear=0;
queue[rear++]=&head;
head.trie=&headTrie;
while(front {
TrieNode* p=queue[front++];
for(int i=0;i<26;i++) 
{
if(p->next[i]!=NULL)
{
queue[rear++]=p->next[i];
p->next[i]->trie=p->trie->next[i];
}
else
{
p->next[i]=p->trie->next[i];
}
}
}
}


3.使用trie图

扫描文章。

从head开始对比,一直照着next来跳转。直达有一个结点的isEnd为true。说明找到字典中的某个单词了。返回true;

否则直到扫描结束都没找到单词,返回false。

bool find(char *s)
{
int i=0;
TrieNode* p=&head;
while(s[i])
{
p=p->next[s[i]-97];
if(p->isEnd) return true;
i++;
}
return false;


题目全代码:

#include
#include
using namespace std;


typedef struct node{
bool isEnd;
struct node* trie;
struct node* next[26];
}TrieNode; 


TrieNode head;
TrieNode headTrie;
TrieNode* queue[1000000+1];


void initNode(TrieNode *p)
{
p->isEnd = 0;
for(int i=0;i<26;i++)
p->next[i]=NULL;
}


void makeTrie(char *w)
{
int i=0;
TrieNode* p=&head;

while(w[i])
{
if(p->next[w[i]-97])
{
p=p->next[w[i]-97];
}
else
{
TrieNode *q=(TrieNode *)malloc(sizeof(TrieNode));
initNode(q);
p->next[w[i]-97]=q;
p=q;
}
i++;
}
p->isEnd=1;
}


void makeTrieMap()
{
int front=0,rear=0;
queue[rear++]=&head;
head.trie=&headTrie;
while(front {
TrieNode* p=queue[front++];
for(int i=0;i<26;i++) 
{
if(p->next[i]!=NULL)
{
queue[rear++]=p->next[i];
p->next[i]->trie=p->trie->next[i];
}
else
{
p->next[i]=p->trie->next[i];
}
}
}
}


bool find(char *s)
{
int i=0;
TrieNode* p=&head;
while(s[i])
{
p=p->next[s[i]-97];
if(p->isEnd) return true;
i++;
}
return false;



int main()
{
int N;
char word[1000000+1];
char str[1000000+1];


initNode(&head);
for(int i=0;i<26;i++)
headTrie.next[i]=&head;

scanf("%d",&N);
while(N--)
{
scanf("%s",word);
makeTrie(word);
}
makeTrieMap();

scanf("%s",str);
if(find(str)) printf("YES");
else printf("NO");

return 0;
}


你可能感兴趣的:(hihocoder,acm,hiho,trie图)