第一次接觸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;
}
題目鏈接
掃碼關注,定期分享技術、算法類文章