接触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