题目连接:http://hihocoder.com/problemset/problem/1036
思路:题目上有题解
这道数据结构是在 Trie树 的基础上构造,所以不懂 Trie树的,先去看看 Trie树。
然后在 Trie树 的基础上,我们增加了一些边,然后树便成了图;
那么需要增加那些边呢?
在这个题目中每个节点都应该有 26 条边,但是 Trie树中有些边是虚的,实际并不存在,而Trie图便是将这些虚边补实后的结果。
为了补实这些边,我们需要对每个节点增加一个数据 trie。
如何求 trie呢?
根节点的trie(第一层节点),我设它为NULL,
第二层节点的trie,我设为根节点,
再往后的层次,每个节点的trie 等于 它父节点的trie 的同一方向上的子节点;
这样就有了 trie了,对于那些虚边,将他们连接到 该节点的父节点的trie 的同一方向上的子节点;
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define MAX 107
using namespace std;
typedef long long ll;
struct NODE{
bool flag;
int pos;
NODE *p,*trie,*next[26];
NODE(){
flag=false;
pos=0;
trie=p=NULL;
for(int i=0;i<26;++i)next[i]=NULL;
}
};
void dfs(NODE *root,string &s,int k){
if(s.length() == k){
root->flag = true;
return;
}
int pos=s[k]-'a';
if(root->next[pos] == NULL)
root->next[pos] = new NODE;
root->next[pos]->p = root;
root->next[pos]->pos = pos;
dfs(root->next[pos],s,k+1);
}
void bfs(NODE *root){
queue<NODE*> q;
for(int i=0;i<26;++i)
if(root->next[i] != NULL){
root->next[i]->trie = root;
q.push(root->next[i]);
}else //虚边
root->next[i]=root;
while(!q.empty()){
NODE *tmp=q.front();
q.pop();
for(int i=0;i<26;++i)
if(tmp->next[i] != NULL){
tmp->next[i]->trie = tmp->trie->next[i];
q.push(tmp->next[i]);
}else //虚边
tmp->next[i] = tmp->trie->next[i];
}
}
void dfs(NODE *root,string& s,bool& flag,int pos){
flag = root->flag;
if(pos == s.length() || flag == true)return;
dfs(root->next[s[pos]-'a'],s,flag,pos+1);
}
int main(){
int n;
NODE *root = new NODE;
cin>>n;
//first step : 构造 Tire树
while(n--){
string s;
cin>>s;
dfs(root,s,0);
}
//second step : 构造 Tire图
bfs(root);
string s;
bool flag=false;
cin>>s;
dfs(root,s,flag,0);
if(flag)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
return 0;
}