接触Trie树是在选拔赛时候遇到一题目,TLE无数次依然无解,赛后发现字符串统计有一利器名曰“字典树”,后来花了一段时间去写Trie,算是基本入门了。
本文主要是介绍一些基本概念,以及一些训练题目,提供大家。
什么叫Trie树?
Trie树即字典树。
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
using namespace std;
template<int Size>
struct trie_node
{
bool terminable; //表示节点为字符串的结尾
int node; //子节点的个数
trie_node *child[Size]; //儿子节点
trie_node():terminable(false), node(0)
{
memset(child,0,sizeof(child)); //初始化节点
}
};
template<int Size,typename Index>
class trie
{
public:
//定义类名
typedef trie_node<Size> node_type;
typedef trie_node<Size> *link_type;
//构造函数
trie(Index i=Index()):index(i) { }
void clear() //清空函数,用于析构
{
clear_node(root);
for(int i=0; i<Size; i++)
root.child[i]=0;
}
template<typename Iterator>
void insert(Iterator begin,Iterator end) //插入
{
link_type cur= &root;//当前插入结点为根
while(begin!=end)
{
if(!cur->child[index[*begin]]) //没有插入过
{
cur->child[index[*begin]]=new node_type;
cur->node++; //插入后,父亲多了一个儿子
}
cur=cur->child[index[*begin]]; //搜儿子
begin++; //迭代器往前走!
}
cur->terminable=true;
}
void insert(const char * str) //重载c风格插入
{
insert(str,str+strlen(str));
}
template <typename Iterator>
bool find(Iterator begin,Iterator end) //查找
{
link_type cur=&root;
while(begin!=end)
{
if(!cur->child[index[*begin]]) //没有节点啊!!!
return false;
cur=cur->child[index[*begin]]; //搜索儿子
begin++;
}
return cur->terminable; //是否为字符串
}
bool find(const char *str) //重载c风格
{
return find(str,str+strlen(str));
}
template<typename Iterator>
bool earse (Iterator begin,Iterator end) //删除字符串
{
bool result;
earse_node(begin,end,root,result);
return result;
}
bool erase(char *str) //c语言风格
{
return earse(str,str+strlen(str));
}
private:
void clear_node(node_type cur) //清空
{
for(int i=0; i<Size; i++)
{
if(cur.child[i]==0)continue; //不存在
clear_node(*cur.child[i]);
delete cur.child[i];
cur.child[i]=0;
if(--cur.node==0) break; //没有节点了
}
}
//一边搜索一边删除
template<typename Iterator>
bool earse_node(Iterator begin ,Iterator end,node_type &cur,bool &result)
{
if(begin==end)
{
result=cur.terminable;
cur.terminalbe=false;
return cur.node==0;
}
//当孩子不存在,结果假,返回假
if(cur.child[index[*begin ]]==0) return !(result=false);
else if(earse_node(begin+1,end,*(cur.child[index[*begin]]),result))
{
delete cur.child[index[*begin]];
cur.child[index[*begin]]=0;
if(--cur.node==0&&cur.terminable==false ) return true;
}
return false;
}
//根
node_type root;
//字符转索引,类似hash
Index index;
};
class IndexClass
{
public:
int operator[](const char key)
{
return key%26; //一个映射
}
};
int main()
{
trie<26,IndexClass> t; //字母就是26,数字就是10
t.insert("tree"); //插入
t.insert("tea");
t.insert("act");
t.insert("adv");
t.insert("ate");
while(scanf("%s",str)!=EOF)//查找
{
if(t.find(str))
{
cout<<"find"<<endl;
}
}
return 0;
}
之后,怎么少得了经典的问题呢?
HDU1251(统计难题)
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
using namespace std;
template<int Size>
struct trie_node
{
bool terminable; //表示节点为字符串的结尾
int node; //子节点的个数
trie_node *child[Size]; //儿子节点
trie_node():terminable(false), node(0)
{
memset(child,0,sizeof(child)); //初始化节点
}
};
template<int Size,typename Index>
class trie
{
public:
//定义类名
typedef trie_node<Size> node_type;
typedef trie_node<Size> *link_type;
//构造函数
trie(Index i=Index()):index(i) { }
void clear() //清空函数,用于析构
{
clear_node(root);
for(int i=0; i<Size; i++)
root.child[i]=0;
}
//插入
template<typename Iterator>
void insert(Iterator begin,Iterator end){
link_type cur= &root;//当前插入结点为根
while(begin!=end){
if(cur->child[index[*begin]]){//插入过
cur=cur->child[index[*begin]];
++(cur->node);
}else{
cur->child[index[*begin]]=new node_type; //这里这里!!!不一样!!!!
++(cur->child[index[*begin]]->node);
cur=cur->child[index[*begin]];
}
begin++; //迭代器往前走!
}
cur->terminable=true;
}
void insert(const char * str) //重载c风格插入
{
insert(str,str+strlen(str));
}
template <typename Iterator>
bool find(Iterator begin,Iterator end) //查找
{
link_type cur=&root;
while(begin!=end)
{
if(!cur->child[index[*begin]]) //没有节点啊!!!
return false;
cur=cur->child[index[*begin]]; //搜索儿子
begin++;
}
return cur->terminable; //是否为字符串
}
bool find(const char *str) //重载c风格
{
return find(str,str+strlen(str));
}
template <typename Iterator>
int findNum(Iterator begin,Iterator end){
link_type cur=&root;
while(begin!=end){
if(!cur->child[index[*begin]]) //没有节点啊!!!
return 0;
cur=cur->child[index[*begin]];
begin++;
}
return cur->node; //是否为字符串
}
//重载c风格
int findNum(const char *str){
return findNum(str,str+strlen(str));
}
template<typename Iterator>
bool earse (Iterator begin,Iterator end) //删除字符串
{
bool result;
earse_node(begin,end,root,result);
return result;
}
bool erase(char *str) //c语言风格
{
return earse(str,str+strlen(str));
}
private:
void clear_node(node_type cur) //清空
{
for(int i=0; i<Size; i++)
{
if(cur.child[i]==0)continue; //不存在
clear_node(*cur.child[i]);
delete cur.child[i];
cur.child[i]=0;
if(--cur.node==0) break; //没有节点了
}
}
//一边搜索一边删除
template<typename Iterator>
bool earse_node(Iterator begin ,Iterator end,node_type &cur,bool &result)
{
if(begin==end)
{
result=cur.terminable;
cur.terminalbe=false;
return cur.node==0;
}
//当孩子不存在,结果假,返回假
if(cur.child[index[*begin ]]==0) return !(result=false);
else if(earse_node(begin+1,end,*(cur.child[index[*begin]]),result))
{
delete cur.child[index[*begin]];
cur.child[index[*begin]]=0;
if(--cur.node==0&&cur.terminable==false ) return true;
}
return false;
}
//根
node_type root;
//字符转索引,类似hash
Index index;
};
class IndexClass
{
public:
int operator[](const char key)
{
return key%26; //一个映射
}
};
int main(){
trie<26,IndexClass> t;
char s[11];
while(gets(s) && s[0])
{
t.insert( s);
}
while(gets(s))
{
printf("%d\n", t.findNum(s));
}
return 0;
}HDU1671
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<vector>
using namespace std;
#define MAXN 10
template<int Size>
struct trie_node
{
bool terminable; //表示节点为字符串的结尾
int node; //子节点的个数
trie_node *child[Size]; //儿子节点
trie_node():terminable(false), node(0)
{
memset(child,0,sizeof(child)); //初始化节点
}
};
template<int Size,typename Index>
class trie
{
public:
//定义类名
typedef trie_node<Size> node_type;
typedef trie_node<Size> *link_type;
//构造函数
trie(Index i=Index()):index(i) { }
//清空函数,用于析构
void clear()
{
clear_node(root);
for(int i=0; i<Size; i++)
root.child[i]=0;
}
//插入
template<typename Iterator>
void insert(Iterator begin,Iterator end)
{
link_type cur= &root;//当前插入结点为根
while(begin!=end)
{
if(cur->child[index[*begin]]) //插入过
{
cur=cur->child[index[*begin]];
cur->node++;
}
else
{
cur->child[index[*begin]]=new node_type;
cur->child[index[*begin]]->node++;
cur=cur->child[index[*begin]];
}
begin++; //迭代器往前走!
}
cur->terminable=true;
}
//重载c风格插入
void insert(const char * str)
{
insert(str,str+strlen(str));
}
//插入
template<typename Iterator>
bool insert2(Iterator begin,Iterator end)
{
link_type cur= &root;//当前插入结点为根
bool flag=0;
while(begin!=end)
{
if(cur->child[index[*begin]]) //插入过
{
if(cur->child[index[*begin]]->terminable==true){
flag=1;
}
cur=cur->child[index[*begin]];
cur->node++;
}
else
{
cur->child[index[*begin]]=new node_type;
cur->child[index[*begin]]->node++;
cur=cur->child[index[*begin]];
}
begin++; //迭代器往前走!
}
cur->terminable=true;
return flag;
}
//重载c风格插入
bool insert2(const char * str)
{
return insert2(str,str+strlen(str));
}
//查找
template <typename Iterator>
bool find(Iterator begin,Iterator end)
{
link_type cur=&root;
while(begin!=end)
{
if(!cur->child[index[*begin]]) //没有节点啊!!!
return false;
cur=cur->child[index[*begin]];
begin++;
}
return cur->terminable; //是否为字符串
}
//重载c风格
bool find(const char *str)
{
return find(str,str+strlen(str));
}
//查找节点数目
template <typename Iterator>
int findNum(Iterator begin,Iterator end)
{
link_type cur=&root;
while(begin!=end)
{
if(!cur->child[index[*begin]]) //没有节点啊!!!
return 0;
cur=cur->child[index[*begin]];
begin++;
}
return cur->node; //是否为字符串
}
//重载c风格
int findNum(const char *str)
{
return findNum(str,str+strlen(str));
}
//查找前缀
template <typename Iterator>
bool findPre(Iterator begin,Iterator end)
{
link_type cur=&root;
while(begin!=end)
{
if(!cur->child[index[*begin]]) //没有节点啊!!!
return false;
if(cur->terminable) break;
cur=cur->child[index[*begin]];
begin++;
}
return begin!=end; //是否为字符串
}
bool findPre(const char *str){
return findPre(str,str+strlen(str));
}
//删除字符串
template<typename Iterator>
bool earse (Iterator begin,Iterator end)
{
bool result;
earse_node(begin,end,root,result);
return result;
}
//c语言风格
bool erase(char *str)
{
return earse(str,str+strlen(str));
}
template<typename Functor>
void traverse(Functor &execute =Functor())
{
visit_node(root,execute);
}
private:
//访问结点
template<typename Functor>
void visit_node(node_type cur,Functor &execute)
{
execute(cur);
for(int i=0; i<Size; i++) //dfs
{
if(cur.child[i]==0) continue;
visit_node(*cur.child[i],execute);
}
}
//清空
void clear_node(node_type cur)
{
for(int i=0; i<Size; i++)
{
if(cur.child[i]==0)continue; //不存在
clear_node(*cur.child[i]);
delete cur.child[i];
cur.child[i]=0;
if(--cur.node==0) break; //没有节点了
}
}
//一边搜索一边删除
template<typename Iterator>
bool earse_node(Iterator begin ,Iterator end,node_type &cur,bool &result)
{
if(begin==end)
{
result=cur.terminable;
cur.terminalbe=false;
return cur.node==0;
}
//当孩子不存在,结果假,返回假
if(cur.child[index[*begin ]]==0) return !(result=false);
else if(earse_node(begin+1,end,*(cur.child[index[*begin]]),result))
{
delete cur.child[index[*begin]];
cur.child[index[*begin]]=0;
if(--cur.node==0&&cur.terminable==false ) return true;
}
return false;
}
//根
node_type root;
//字符转索引,类似hash
Index index;
};
class IndexClass
{
public:
int operator[](const char key)
{
return key%MAXN; //一个映射
}
};
char s[10000][11];
int main()
{
trie<MAXN,IndexClass> t;
int T,n,i;
// freopen("in.txt","r",stdin);
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
t.clear();
for(i=0;i<n;i++){
scanf("%s",s[i]);
t.insert(s[i]);
}
for(i=0;i<n;i++){
if(t.findPre(s[i])){
puts("NO");
break;
}
}
if(i==n) puts("YES");
}
return 0;
}#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
using namespace std;
template<int Size>
struct trie_node{
bool terminable; //???????????
int node; //??????
int cnt;
trie_node *child[Size]; //????
trie_node():terminable(false), node(0),cnt(0){
memset(child,0,sizeof(child)); //?????
}
};
int maxN;
char sb[30];
char s[30];
template<int Size,typename Index>
class trie{
public:
//????
typedef trie_node<Size> node_type;
typedef trie_node<Size> *link_type;
//????
trie(Index i=Index()):index(i){ }
//????,????
void clear(){
clear_node(root);
for(int i=0;i<Size;i++)
root.child[i]=0;
}
//??
template<typename Iterator>
bool insert(Iterator begin,Iterator end){
link_type cur= &root;//????????
while(begin!=end){
if(!cur->child[index[*begin]]){//???
cur->child[index[*begin]]=new node_type;
cur->node++;
}
cur=cur->child[index[*begin]];
begin++; //??????!
}
cur->terminable=true;
cur->cnt++;
if(cur->cnt> maxN){
maxN=cur->cnt;
// cout<<maxN;
return true;
}
return false;
}
//??c????
void insert( char * str){
if(insert(str,str+strlen(str))){
strcpy(sb,str);
};
}
private:
//??
void clear_node(node_type cur){
for(int i=0;i<Size;i++){
if(cur.child[i]==0)continue; //???
clear_node(*cur.child[i]);
delete cur.child[i];
cur.child[i]=0;
if(--cur.node==0) break; //?????
}
}
//?
node_type root;
//?????,??hash
Index index;
};
class IndexClass{
public:
int operator[](const char key){
return key%26; //????
}
};
int main(){
trie<26,IndexClass> t;
//freopen("in.txt","r",stdin);
int n;
while(scanf("%d",&n)&&n)
{
maxN=-1;
for(int i=0;i<n;i++){
scanf("%s",s);
t.insert(s);
// cout<<maxN<<endl;
}
printf("%s\n",sb);
t.clear();
}
return 0;
}
HDU1075
http://acm.hdu.edu.cn/showproblem.php?pid=1075
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
using namespace std;
char str1[12];
char str2[12];
char st[3100];
template<int Size>
struct trie_node
{
bool terminable; //表示节点为字符串的结尾
int node; //子节点的个数
char str[12];
trie_node *child[Size]; //儿子节点
trie_node():terminable(false), node(0)
{
memset(child,0,sizeof(child)); //初始化节点
}
};
template<int Size,typename Index>
class trie
{
public:
//定义类名
typedef trie_node<Size> node_type;
typedef trie_node<Size> *link_type;
//构造函数
trie(Index i=Index()):index(i) { }
//清空函数,用于析构
void clear()
{
clear_node(root);
for(int i=0; i<Size; i++)
root.child[i]=0;
}
//插入
template<typename Iterator>
void insert(Iterator begin,Iterator end)
{
link_type cur= &root;//当前插入结点为根
while(begin!=end)
{
if(cur->child[index[*begin]]) //插入过
{
cur=cur->child[index[*begin]];
++(cur->node);
}
else
{
cur->child[index[*begin]]=new node_type;
++(cur->child[index[*begin]]->node);
cur=cur->child[index[*begin]];
}
begin++; //迭代器往前走!
}
cur->terminable=true;
int len=strlen(str1);
for(int i=0; i<=len; i++)
cur->str[i]=str1[i];
}
//重载c风格插入
void insert(const char * str)
{
insert(str,str+strlen(str));
}
//查找
template <typename Iterator>
bool find(Iterator begin,Iterator end)
{
link_type cur=&root;
while(begin!=end)
{
if(!cur->child[index[*begin]]) //没有节点啊!!!
return false;
cur=cur->child[index[*begin]];
begin++;
}
// printf("%s sb",cur->str);
if(cur->terminable)
{
printf("%s",cur->str);
return true;
}
return false; //是否为字符串
}
//重载c风格
bool find(const char *str)
{
return find(str,str+strlen(str));
}
private:
//清空
void clear_node(node_type cur)
{
for(int i=0; i<Size; i++)
{
if(cur.child[i]==0)continue; //不存在
clear_node(*cur.child[i]);
delete cur.childe[i];
cur.child[i]=0;
if(--cur.node==0) break; //没有节点了
}
}
//根
node_type root;
//字符转索引,类似hash
Index index;
};
class IndexClass
{
public:
int operator[](const char key)
{
return key%26; //一个映射
}
};
int main()
{
trie<26,IndexClass> t;
scanf("%s",str2) ;
while(scanf("%s",str1))
{
if(str1[0]==‘E‘)
{
break;
}
scanf("%s",str2);
t.insert(str2);
}
scanf("%s",str2);
getchar();
while(gets(st))
{
if(st[0]==‘E‘)
{
break;
}
int len=strlen(st);
int bg=0;
for(int i=0; i<len; i++)
{
if(st[i]>=‘a‘&&st[i]<=‘z‘)
{
continue;
}
if(!t.find(st+bg,st+i))
{
for(int j=bg; j<i; j++)
printf("%c",st[j]);
};
if(st[i]) printf("%c",st[i]);
bg=i+1;
}
puts("");
}
return 0;
}WAcode:#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
using namespace std;
char str1[12];
char str2[12];
char st[3100];
template<int Size>
struct trie_node
{
bool terminable; //表示节点为字符串的结尾
int node; //子节点的个数
char str[12];
trie_node *child[Size]; //儿子节点
trie_node():terminable(false), node(0)
{
memset(child,0,sizeof(child)); //初始化节点
}
};
template<int Size,typename Index>
class trie
{
public:
//定义类名
typedef trie_node<Size> node_type;
typedef trie_node<Size> *link_type;
//构造函数
trie(Index i=Index()):index(i) { }
//清空函数,用于析构
void clear()
{
clear_node(root);
for(int i=0; i<Size; i++)
root.child[i]=0;
}
//插入
template<typename Iterator>
void insert(Iterator begin,Iterator end)
{
link_type cur= &root;//当前插入结点为根
while(begin!=end)
{
if(cur->child[index[*begin]]) //插入过
{
cur=cur->child[index[*begin]];
++(cur->node);
}
else
{
cur->child[index[*begin]]=new node_type;
++(cur->child[index[*begin]]->node);
cur=cur->child[index[*begin]];
}
begin++; //迭代器往前走!
}
cur->terminable=true;
int len=strlen(str1);
for(int i=0; i<len; i++)
cur->str[i]=str1[i];
}
//重载c风格插入
void insert(const char * str)
{
insert(str,str+strlen(str));
}
//查找
template <typename Iterator>
bool find(Iterator begin,Iterator end)
{
link_type cur=&root;
while(begin!=end)
{
if(!cur->child[index[*begin]]) //没有节点啊!!!
return false;
cur=cur->child[index[*begin]];
begin++;
}
// printf("%s sb",cur->str);
if(cur->terminable)
{
printf("%s",cur->str);
return true;
}
return false; //是否为字符串
}
//重载c风格
bool find(const char *str)
{
return find(str,str+strlen(str));
}
private:
//清空
void clear_node(node_type cur)
{
for(int i=0; i<Size; i++)
{
if(cur.child[i]==0)continue; //不存在
clear_node(*cur.child[i]);
delete cur.childe[i];
cur.child[i]=0;
if(--cur.node==0) break; //没有节点了
}
}
//根
node_type root;
//字符转索引,类似hash
Index index;
};
class IndexClass
{
public:
int operator[](const char key)
{
return key%26; //一个映射
}
};
int main()
{
trie<26,IndexClass> t;
scanf("%s",str2) ;
while(scanf("%s",str1))
{
if(str1[0]==‘E‘)
{
break;
}
scanf("%s",str2);
t.insert(str2);
}
scanf("%s",str2);
getchar();
while(gets(st))
{
if(st[0]==‘E‘)
{
break;
}
int len=strlen(st);
int bg=0;
for(int i=0; i<len; i++)
{
if(st[i]>=‘a‘&&st[i]<=‘z‘)
{
continue;
}
if(!t.find(st+bg,st+i))
{
for(int j=bg; j<i; j++)
printf("%c",st[j]);
};
if(st[i]) printf("%c",st[i]);
bg=i+1;
}
puts("");
}
return 0;
}(差别就在字符串copy 上没有拷贝上‘\0‘……,也就是st[len])
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
template<int Size>
struct trie_node{
bool terminable; //表示节点为字符串的结尾
int node; //子节点的个数
trie_node *child[Size]; //儿子节点
trie_node():terminable(false), node(0){
memset(child,0,sizeof(child)); //初始化节点
}
};
template<int Size,typename Index>
class trie{
public:
//定义类名
typedef trie_node<Size> node_type;
typedef trie_node<Size> *link_type;
//构造函数
trie(Index i=Index()):index(i){ }
//清空函数,用于析构
void clear(){
clear_node(root);
for(int i=0;i<Size;i++)
root.child[i]=0;
}
//插入
template<typename Iterator>
void insert(Iterator begin,Iterator end){
link_type cur= &root;//当前插入结点为根
while(begin!=end){
if(cur->child[index[*begin]]){//插入过
cur=cur->child[index[*begin]];
++(cur->node);
}else{
cur->child[index[*begin]]=new node_type;
++(cur->child[index[*begin]]->node);
cur=cur->child[index[*begin]];
}
// cout<<*begin;
begin++; //迭代器往前走!
}
cur->terminable=true;
// cout<<cur->id<<endl;
}
//重载c风格插入
void insert(const char * str){
insert(str,str+strlen(str));
}
//查找
template <typename Iterator>
bool find(Iterator begin,Iterator end){
link_type cur=&root;
while(begin!=end){
if(!cur->child[index[*begin]])return false; //我在这里re了无数次…忧桑……
cur=cur->child[index[*begin]];
begin++;
}
// cout<<*begin<<" "<<*end<<"sb" <<endl;
return cur->terminable;
}
//重载c风格
bool find(const char *str){
return find(str,str+strlen(str));
}
private:
//清空
void clear_node(node_type cur){
for(int i=0;i<Size;i++){
if(cur.child[i]==0)continue; //不存在
clear_node(*cur.child[i]);
delete cur.childe[i];
cur.child[i]=0;
if(--cur.node==0) break; //没有节点了
}
}
//根
node_type root;
//字符转索引,类似hash
Index index;
};
class IndexClass{
public:
int operator[](const char key){
return key%26; //一个映射
}
};
char str[50005][100];
int main(){
trie<26,IndexClass> t;
int i=0;
while(scanf("%s",str[i])!=EOF){
// cout<<str[i];
t.insert(str[i]);
i++;
}
for(int j=0;j<i;j++){
int len=strlen(str[j]);
for(int p=1;p<=len-1;p++){
if(t.find(str[j],str[j]+p)){
if(t.find(str[j]+p)){
printf("%s\n",str[j]);
break;
}
}
}
}
return 0;
}尽管我上面这个做法已经OK了,但是这是参考了别人,下面是我完全按自己想法写的,程序员最高兴的莫过于可以将自己的想法实现。#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
template<int Size>
struct trie_node{
bool terminable; //表示节点为字符串的结尾
int node; //子节点的个数
trie_node *child[Size]; //儿子节点
trie_node():terminable(false), node(0){
memset(child,0,sizeof(child)); //初始化节点
}
};
template<int Size,typename Index>
class trie{
public:
//定义类名
typedef trie_node<Size> node_type;
typedef trie_node<Size> *link_type;
//构造函数
trie(Index i=Index()):index(i){ }
//清空函数,用于析构
void clear(){
clear_node(root);
for(int i=0;i<Size;i++)
root.child[i]=0;
}
//插入
template<typename Iterator>
void insert(Iterator begin,Iterator end){
link_type cur= &root;//当前插入结点为根
while(begin!=end){
if(cur->child[index[*begin]]){//插入过
cur=cur->child[index[*begin]];
++(cur->node);
}else{
cur->child[index[*begin]]=new node_type;
++(cur->child[index[*begin]]->node);
cur=cur->child[index[*begin]];
}
// cout<<*begin;
begin++; //迭代器往前走!
}
cur->terminable=true;
// cout<<cur->id<<endl;
}
//重载c风格插入
void insert(const char * str){
insert(str,str+strlen(str));
}
//查找
template <typename Iterator>
bool find(Iterator begin,Iterator end,int i){
link_type cur=&root;
while(begin!=end){
if(cur->terminable){
if(i>1) return false;
if( find(begin,end,i+1))return true;
}
if(!cur->child[index[*begin]]) return false;
cur=cur->child[index[*begin]];
begin++;
}
if(!cur->terminable){
return false;
}
return i==1;
}
//重载c风格
bool find(const char *str,int i){
return find(str,str+strlen(str),i);
}
private:
//清空
void clear_node(node_type cur){
for(int i=0;i<Size;i++){
if(cur.child[i]==0)continue; //不存在
clear_node(*cur.child[i]);
delete cur.child[i];
cur.child[i]=0;
if(--cur.node==0) break; //没有节点了
}
}
//根
node_type root;
//字符转索引,类似hash
Index index;
};
class IndexClass{
public:
int operator[](const char key){
return key%26; //一个映射
}
};
char str[50005][50];
int main(){
trie<26,IndexClass> t;
int i=0;
//freopen("in.txt","r",stdin);
while(scanf("%s",str[i])!=EOF){
// cout<<str[i];
t.insert(str[i]);
i++;
}
for(int j=0;j<i;j++){
if(t.find(str[j],0)){ //类似与dfss
printf("%s\n",str[j]);
}
}
return 0;
}HDU1857,逆向思维的trie,可以参考我之前写过的
http://acm.hdu.edu.cn/showproblem.php?pid=1857
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
template<int Size>
struct trie_node{
bool terminable; //表示节点为字符串的结尾
int node; //子节点的个数
int id;
trie_node *child[Size]; //儿子节点
trie_node():terminable(false), node(0){
memset(child,0,sizeof(child)); //初始化节点
}
};
int RR[10200],CC[10200];
template<int Size,typename Index>
class trie{
public:
//定义类名
typedef trie_node<Size> node_type;
typedef trie_node<Size> *link_type;
//构造函数
trie(Index i=Index()):index(i){ }
//清空函数,用于析构
void clear(){
clear_node(root);
for(int i=0;i<Size;i++)
root.child[i]=0;
}
//插入
template<typename Iterator>
void insert(Iterator begin,Iterator end,int i){
link_type cur= &root;//当前插入结点为根
while(begin!=end){
if(cur->child[index[*begin]]){//插入过
cur=cur->child[index[*begin]];
++(cur->node);
}else{
cur->child[index[*begin]]=new node_type;
++(cur->child[index[*begin]]->node);
cur=cur->child[index[*begin]];
}
begin++; //迭代器往前走!
}
cur->terminable=true;
cur->id=i;
}
//重载c风格插入
void insert(const char * str,int i){
insert(str,str+strlen(str), i);
}
//查找
template <typename Iterator>
void find(Iterator begin,Iterator end,int r,int c){
link_type cur=&root;
while(begin!=end){
if(cur->terminable){
if(RR[cur->id]==0){
RR[cur->id]=r;
CC[cur->id]=c;
}
}
if(!cur->child[index[*begin]]) //没有节点啊!!!
return ;
cur=cur->child[index[*begin]];
begin++;
}
if( cur->terminable) {//是否为字符串
if(RR[cur->id]==0){
RR[cur->id]=r;
CC[cur->id]=c;
}
}
}
//重载c风格
void find(const char *str,int r,int c){
find(str,str+strlen(str),r,c);
}
private:
//清空
void clear_node(node_type cur){
for(int i=0;i<Size;i++){
if(cur.child[i]==0)continue; //不存在
clear_node(*cur.child[i]);
delete cur.childe[i];
cur.child[i]=0;
if(--cur.node==0) break; //没有节点了
}
}
//根
node_type root;
//字符转索引,类似hash
Index index;
};
class IndexClass{
public:
int operator[](const char key){
return key%26; //一个映射
}
};
char cc[501][501];
char s[21];
int mini(int a,int b){
return a>b?b:a;
}
int main(){
trie<26,IndexClass> t;
int R,C,i,j,l,ed;
scanf("%d%d",&R,&C);
getchar(); //读掉回车
for( i=0;i<R;i++)
{
gets(cc[i]);
}
int N=0;
while(gets(s)&&s[0]!=‘-‘){
if(s[0]){
t.insert(s,N); //用每一个要查找的单词构树
N++;
}
}
for(i=0;i<R;i++)
for( j=0;j<C;j++){
//向下
memset(s,0,sizeof(s));
if(i+20<R) ed=20;
else ed=R-i;
for(l=0;l<ed;l++){
s[l]=cc[i+l][j];
}
t.find(s,i+1,j+1);
//向右
memset(s,0,sizeof(s));
if(j+20<C) ed=20;
else ed=C-j;
for( l=0;l<ed;l++){
s[l]=cc[i][j+l];
}
t.find(s,i+1,j+1);
//右下
memset(s,0,sizeof(s));
if(i+20<R&&j+20<C) ed=20;
else ed=mini(C-j,R-i);
for( l=0;l<ed;l++){
s[l]=cc[i+l][j+l];
}
t.find(s,i+1,j+1);
}
for( i=0;i<N;i++){
if(RR[i]!=0||CC[i]!=0)
printf("%d %d\n",RR[i]-1,CC[i]-1);
else puts("-1 -1");
}
return 0;
}原文地址:http://blog.csdn.net/dengyaolongacmblog/article/details/25074499