又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来节约存储空间,最大限度地减少无谓的字符串比较,查询效率比哈希表高。
假设有abc,abcd,abd, b, bcd,efg,hii这7个单词,可构建字典树如下:
查找一个字符串时,我们只需从根结点按字符串中字符出现顺序依次往下走。如果到最后字符串结束时,对应的结点标记为红色,则该字符串存在;否则不存在。
插入时也只需从根结点往下遍历,碰到已存在的字符结点就往下遍历,否则,建立新结点;最后标记最后一个字符的结点为红色即可。
性质
它有3个基本性质:
根节点不包含字符,除根节点外每一个节点都只包含一个字符。
从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
每个节点的所有子节点包含的字符都不相同。
基本操作
其基本操作有:查找 插入和删除,当然删除操作比较少见.我在这里只是实现了对整个树的删除操作,至于单个word的删除操作也很简单.
搜索字典项目的方法为:
(1) 从根结点开始一次搜索;
(2) 取得要查找关键词的第一个字母,并根据该字母选择对应的子树并转到该子树继续进行检索;
(3) 在相应的子树上,取得要查找关键词的第二个字母,并进一步选择对应的子树进行检索。
(4) 迭代过程……
(5) 在某个结点处,关键词的所有字母已被取出,则读取附在该结点上的信息,即完成查找。
其他操作类似处理
以上内容来自百度百科:。对应练习:ZOJ1109 HDU1251
ZOJ1109 Language of FatMouse
map方法 1320MS 9556K
#include < iostream >
#include < string >
#include < map >
#pragma warning (disable:4786)
using namespace std;
int main()
{
map < string , string > m;
int len,i;
char str[ 40 ],a[ 20 ],b[ 20 ];
while ( 1 )
{
gets(str);
len = strlen(str);
if (len == 0 )
break ;
for (i = 0 ;str[i] != ' ' ;i ++ );
strncpy(a,str,i);
a[i] = 0 ;
strncpy(b,str + i + 1 ,len - i - 1 );
b[len - i - 1 ] = 0 ;
m[b] = a;
}
map < string , string > ::iterator it;
while (scanf( " %s " ,str) != EOF)
{
it = m.find(str);
if (it != m.end())
cout << ( * it).second << endl;
else
puts( " eh " );
}
return 0 ;
}
字典树:140MS 14960K
#include < stdio.h >
#include < stdlib.h >
#include < string .h >
#define N 100006
typedef struct node{
char s[ 12 ];
int h;
struct node * next[ 26 ];
} * Tree,T;
void init(Tree & root)
{
root = (Tree)malloc( sizeof (T));
root -> h = 0 ;
for ( int i = 0 ;i < 26 ;i ++ )
root -> next[i] = NULL;
}
void insert( char path[], char s[],Tree root)
{
int len,i,j;
len = strlen(path);
for (i = 0 ;i < len;i ++ )
{
if (root -> next[path[i] - ' a ' ] == NULL)
{
Tree t = (Tree)malloc( sizeof (T));
for (j = 0 ;j < 26 ;j ++ )
{
t -> next[j] = NULL;
t -> h = 0 ;
}
root -> next[path[i] - ' a ' ] = t;
}
root = root -> next[path[i] - ' a ' ];
}
root -> h = 1 ;
strcpy(root -> s,s);
}
void find( char s[],Tree root)
{
int len,i;
len = strlen(s);
for (i = 0 ;i < len;i ++ )
{
if (root -> next[s[i] - ' a ' ] != NULL)
root = root -> next[s[i] - ' a ' ];
else
break ;
}
if (i == len && root -> h == 1 )
puts(root -> s);
else
puts( " eh " );
}
int main()
{
Tree root;
int len,i;
char str[ 25 ],a[ 12 ],b[ 12 ];
init(root);
while ( 1 )
{
gets(str);
len = strlen(str);
if (len == 0 )
break ;
for (i = 0 ;str[i] != ' ' ;i ++ );
strncpy(a,str,i);
a[i] = 0 ;
strncpy(b,str + i + 1 ,len - i - 1 );
b[len - i - 1 ] = 0 ;
insert(b,a,root);
}
while (scanf( " %s " ,str) != EOF)
find(str,root);
return 0 ;
}
HDU1251 统计难题 140MS 43736K
#include < stdio.h >
#include < stdlib.h >
#include < string .h >
typedef struct node{
int cnt;
struct node * next[ 26 ];
} * Tree,T;
Tree root;
void insert( char * str) // 建字典树
{
int i;
Tree p,newnode;
p = root;
for (; * str;str ++ )
{
if (p -> next[ * str - ' a ' ] != NULL)
{
p = p -> next[ * str - ' a ' ];
p -> cnt ++ ;
}
else
{
newnode = (Tree)malloc( sizeof (T));
for (i = 0 ;i < 26 ;i ++ )
newnode -> next[i] = NULL;
p -> next[ * str - ' a ' ] = newnode;
p = p -> next[ * str - ' a ' ];
p -> cnt = 1 ;
}
}
}
int find( char * str) // 查找
{
Tree p;
p = root;
for (; * str;str ++ )
{
if (p -> next[ * str - ' a ' ] != NULL)
p = p -> next[ * str - ' a ' ];
else
return 0 ;
}
return p -> cnt;
}
int main()
{
int i;
char str[ 20 ];
root = (Tree)malloc( sizeof (T));
for (i = 0 ;i < 26 ;i ++ )
root -> next[i] = NULL;
root -> cnt = 0 ;
while (gets(str))
{
if (strcmp(str, "" ) == 0 )
break ;
insert(str);
}
while (gets(str))
printf( " %d\n " ,find(str));
return 0 ;
}
PKU1204 Word Puzzles
字典树:1485MS 14320K(对给定的单词建树,对表进行暴力search)
#include < stdio.h >
#include < string .h >
#include < stdlib.h >
#define N 1002
typedef struct tree{
int count;
struct tree * next[ 26 ];
} * Tree,T;
Tree root;
int l,c,w;
char map[N][N];
int result[N][ 3 ];
int dir[ 8 ][ 2 ] = {{ - 1 , 0 },{ - 1 , 1 },{ 0 , 1 },{ 1 , 1 },{ 1 , 0 },{ 1 , - 1 },{ 0 , - 1 },{ - 1 , - 1 }};
void insert( char * s, int con)
{
Tree p = root,q;
for ( int i = 0 ;s[i];i ++ )
{
if (p -> next[s[i] - ' A ' ] == NULL)
{
q = (Tree)malloc( sizeof (T));
memset(q -> next, 0 , sizeof (q -> next));
q -> count =- 1 ;
p -> next[s[i] - ' A ' ] = q;
}
p = p -> next[s[i] - ' A ' ];
}
p -> count = con;
}
void search( int x, int y, int k)
{
int x1 = x,y1 = y;
Tree p = root;
while (x1 >= 0 && x1 < l && y1 >= 0 && y1 < c)
{
int id = map[x1][y1] - ' A ' ;
if (p -> next[id] == NULL)
break ;
else
p = p -> next[id];
if (p -> count !=- 1 )
{
result[p -> count][ 0 ] = x;
result[p -> count][ 1 ] = y;
result[p -> count][ 2 ] = k + ' A ' ;
}
x1 += dir[k][ 0 ]; y1 += dir[k][ 1 ];
}
}
void slove()
{
int i,j,k;
for (i = 0 ;i < l;i ++ )
for (j = 0 ;j < c;j ++ )
for (k = 0 ;k < 8 ;k ++ )
search(i,j,k);
for (i = 0 ;i < w;i ++ )
printf( " %d %d %c\n " ,result[i][ 0 ],result[i][ 1 ],result[i][ 2 ]);
}
int main()
{
int i;
char word[N];
scanf( " %d%d%d " , & l, & c, & w);
getchar();
root = (Tree)malloc( sizeof (T));
memset(root -> next, 0 , sizeof (root -> next));
for (i = 0 ;i < l;i ++ )
gets(map[i]);
for (i = 0 ;i < w;i ++ )
{
gets(word);
insert(word,i);
}
slove();
return 0 ;
}
据说这题还可以用AC自动机实现,不了解AC自动机,有待提高……
HDU1075 同ZOJ1109同一道理,字典树基本应用。
map方法 3375MS 42368K 752B
#include < iostream >
#include < string >
#include < map >
using namespace std;
int main()
{
map < string , string > M;
string a,b;
cin >> a;
while (cin >> a,a != " END " )
{
cin >> b;
M[b] = a;
}
cin >> a;
getchar();
char tmp[ 3005 ];
while (gets(tmp),strcmp(tmp, " END " ))
{
int len = strlen(tmp);
tmp[len ++ ] = ' ' ;
tmp[len] = 0 ;
b = "" ;
for ( int i = 0 ;i < len;i ++ )
{
if ( ! islower(tmp[i]))
{
if (M[b] != "" )
cout << M[b];
else
cout << b;
b = "" ;
if (i != len - 1 )
cout << tmp[i];
}
else
b += tmp[i];
}
cout << endl;
}
return 0 ;
}
字典树:437MS 59796K 1274B(可以用做模板了吧)
#include < stdio.h >
#include < string .h >
#include < ctype.h >
#include < stdlib.h >
typedef struct node{
node * next[ 26 ];
int h;
char word[ 12 ];
node()
{
h = 0 ;
memset(next, 0 , sizeof (next));
}
} * Tree,T;
Tree root = new node();
void insert( char * eng, char * mar)
{
Tree p = root;
while ( * mar)
{
int id =* mar - ' a ' ;
if (p -> next[id] == NULL)
p -> next[id] = new node();
p = p -> next[id];
mar ++ ;
}
p -> h = 1 ;
strcpy(p -> word,eng);
}
char * find( char * str)
{
Tree p = root;
while ( * str)
{
int id =* str - ' a ' ;
if (p -> next[id] == NULL)
break ;
p = p -> next[id];
str ++ ;
}
if ( * str == NULL && p -> h == 1 )
return p -> word;
else
return NULL;
}
int main()
{
int i,k,len;
char a[ 12 ],b[ 12 ],tmp[ 3005 ],tp[ 3005 ];
char * p;
scanf( " %s " ,a);
while (scanf( " %s " ,a) && strcmp(a, " END " ) != 0 )
{
scanf( " %s " ,b);
insert(a,b);
}
scanf( " %s " ,a);
getchar();
k = 0 ;
while (gets(tmp),strcmp(tmp, " END " ))
{
len = strlen(tmp);
tmp[len ++ ] = ' ' ;
tmp[len] = 0 ;
for (i = 0 ;i < len;i ++ )
{
if ( ! islower(tmp[i]))
{
tp[k] = 0 ;
k = 0 ;
p = find(tp);
if (p)
printf( " %s " ,p);
else
printf( " %s " ,tp);
if (i != len - 1 )
putchar(tmp[i]);
}
else
tp[k ++ ] = tmp[i];
}
puts( "" );
}
return 0 ;
}