赞
踩
在计算机科学中,Trie树,称前缀树或字典树,是一种有序树,用于保存关联数组,其中的键通常是字符串。与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。一个节点的所有子孙都有相同的前缀,也即是这个节点对应的字符串,而根节点对应空字符串。一般情况下,不是所有的的节点都有对应的值,只有叶子节点和部分内部节点所对应的键才有相关的值。是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常呗搜索引擎系统用于文本词频统计。优点是:最大限度的减少无所谓的字符串比较,查询效率比哈希表高。核心思想是空间换时间。
Trie树是一颗存储多个字符串的树。相邻节点间的边代表一个字符,这样数的每条分支代表一个子串,而树的叶子结点则代表完整的字符串。和普通属不同的地方是:相同的字符串前缀共享同一条分支。举一个例子,字典内容如下:
to, te, A, tea, ted, ten, in, inn
具体如下:
Trie的构建不难,把每个字符串依次的插入到Trie中,插入前先看前缀是否存在,如果存在,就共享即可,否则创建对应的节点和边
s[i] - 'a'
next中
没有该序列号,创建新的即可,否则往前走next数组中的对应序列号没有赋值
,没有次字符串,直接return即可,否则往前继续查找cnt即可
下面是hihoCode上的板子题,可以参考下
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 10;
char S[maxn];
struct Trie{
int next[26];
int cnt;
void init() {
cnt = 0;
memset(next, -1, sizeof next);
}
}T[maxn];
int le;
void Insert(string s) {
int p = 0;
for (int i = 0; i < s.size(); i++) {
int r = s[i] - 'a';
if(T[p].next[r] == -1) {
T[le].init();
T[p].next[r] = le++;
}
p = T[p].next[r];
T[p].cnt++;
}
}
void query(string s) {
int p = 0;
for (int i = 0; i < s.size(); i++) {
int r = s[i] - 'a';
if(T[p].next[r] == -1) {
cout<<0<<endl;
return ;
}
p = T[p].next[r];
}
cout<<T[p].cnt<<endl;
}
int main() {
ios_base::sync_with_stdio(0);
int n;cin>>n;
T[0].init();
le = 1;
for (int i = 0; i < n; i++) {
string s;cin>>s;
Insert(s);
}
int m;cin>>m;
while (m--) {
string s;cin>>s;
query(s);
}
return 0;
}

其他参考例题如下
HUD 1251 统计难题
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 10;
char S[maxn];
struct Trie{
int next[27];
int cnt;
void init() {
cnt = 0;
memset(next, -1, sizeof next);
}
}T[maxn];
int le;
void Insert(string s) {
int p = 0;
for (int i = 0; i < s.size(); i++) {
int r = s[i] - 'a';
if(T[p].next[r] == -1) {
T[le].init();
T[p].next[r] = le++;
}
p = T[p].next[r];
T[p].cnt++;
}
}
void query(string s) {
int p = 0;
for (int i = 0; i < s.size(); i++) {
int r = s[i] - 'a';
if(T[p].next[r] == -1) {
cout<<0<<endl;
return ;
}
p = T[p].next[r];
}
cout<<T[p].cnt<<endl;
}
int main() {
ios_base::sync_with_stdio(0);
T[0].init();
le = 1;
string s;
while (getline(cin,s)) {
if(s.size() == 0) break;
Insert(s);
}
while (getline(cin,s)) {
query(s);
}
return 0;
}

HDU 1075 What Are You Talking About
在根节点设上一个标志即可
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 10;
struct Trie {
int next[26];
int cnt;
bool isfail;
string ss;
void init() {
isfail = false;
cnt = 0;
memset(next, -1, sizeof next);
}
}T[maxn];
int le;
void Insert(string s,string t) {
int p = 0;
for (int i = 0; i < s.size(); i++) {
int r = s[i] - 'a';
if(T[p].next[r] == -1) {
T[le].init();
T[p].next[r] = le++;
}
p = T[p].next[r];
T[p].cnt++;
}
T[p].ss = t;
T[p].isfail = true;
}
string query(string s) {
int p = 0;
for (int i = 0; i < s.size(); i++) {
int r = s[i] - 'a';
if(T[p].next[r] == -1) {
return s;
}
p = T[p].next[r];
}
if(T[p].isfail) {
return T[p].ss;
} else return s;
}
int main() {
T[0].init();
le = 1;
string s;cin>>s;
while (cin>>s,s != "END") {
string t;cin>>t;
Insert(t,s);
}
cin>>s;
getchar();
while (getline(cin,s)) {
if(s == "END") break;
string t;
for (int i = 0; i < s.size();i++) {
if(islower(s[i])) {
t += s[i];
} else {
cout<<query(t);
cout<<s[i];
t.clear();
}
}
cout<<endl;
}
}

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。