第一次接触Trie图,参考了两个文档:
《Trie图的构建、活用与改进-PPT》,里面有一个例子可以参考。
《hihocoder#1036 : Trie图》,题目本身对算法讲解的很详细。
trie图是借助了KMP、后缀的思想,对Trie树做了改进,具体还是以题目本身的讲解为主了。
建图过程最主要的有两步:
- 计算当前节点的后缀节点。
- 为当前节点补全后缀指针。
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <utility>
using namespace std;
typedef struct node{
struct node * c[26],*pre;
int cnt;
}node;
node *root,buf[1000010];
int bufsize=0;
inline node *getnode(){
return buf+bufsize++;
}
char s[1000010];
int main()
{
int n,i,j,k;
scanf("%d",&n);
memset(buf,0,sizeof(buf));
root=buf+0;bufsize=1;
root->pre=root;
for(i=0;i<n;i++){
scanf("%s",s);
node *p=root;
for(j=0;s[j];j++){
k=s[j]-'a';
if(p->c[k]==NULL)
p->c[k]=getnode();
p=p->c[k];
}
p->cnt=1;
}
queue<node*> que;
for(i=0;i<26;i++){
if(root->c[i]==NULL) root->c[i]=root;
else{
root->c[i]->pre=root;
que.push(root->c[i]);
}
}
while(!que.empty()){
node *p=que.front();
que.pop();
p->cnt|=p->pre->cnt;
for(i=0;i<26;i++){
if(p->c[i]==NULL){
p->c[i]=p->pre->c[i];
}else{
p->c[i]->pre=p->pre->c[i];
que.push(p->c[i]);
}
}
}
scanf("%s",s);
node *p=root;
bool flag=false;
for(i=0;s[i];i++){
k=s[i]-'a';
p=p->c[k];
if(p->cnt>0) {
flag=true;
break;
}
}
if(flag==true)
printf("YES\n");
else printf("NO\n");
return 0;
}
题目链接
扫码关注,定期分享技术、算法类文章