Trie是一种树形结构,也叫前缀树。通常用来保存字符串的集合。先举个例子:
如图:这是字符串集合{a,be,ben,book,to,tea}的Trie。我们可以用f[i][j]来保存节点i编号(在这里a,b..z的编号为0,1..25)的子节点。
下面考虑两种操作:插入和查询。查询和插入差不多(这里省略查询),而插入只需要遍历整个字符串S,每次只需要看f[now][idx(S[i])](now是当前节点,这里为了方便,idx函数返回编号)是否存在,不存在就新建结点,然后now往下走,直到遍历完字符串。
但是,我们往往需要在字符串加上附加信息。那么只需要在字符串对应的叶节点上加上附加信息就可以啦!而其他节点的附加信息为0。
这样,我们就能编出Trie了。
//小写字母的Trie
#define root 0
const int Max_size = 26;
const int Maxn = 10010;
struct Trie{
int f[Maxn][Max_size];
int a[Maxn];
int num;
Trie() {num = 1; memset(f[0],0,sizeof(f[0])); }
int idx(char c) {return c - 'a'; }//编号
void insert(char *s,int p)//插入操作 p>0
{
int n = strlen(s) , k = root ;
for(int i=0;i<n;i++)
{
int c = idx(s[i]);
if(!f[k][c])//没有这个节点
{
memset(f[num],0,sizeof(num));
a[num] = 0;//附加信息为0
f[k][c] = num ++;//新建结点
}
k = f[k][c];//往下
}
a[k] = p;//加上附加信息
}
int query(char *s)//查询操作,没有返回-1,有则返回附加信息
{
int n = strlen(s) , k = root;
for(int i=0;i<n;i++)
{
int c = idx(s[i]);
if(!f[k][c]) //没有节点
return -1;
else
k = f[k][c];//往下
}
if(!a[k]) return -1;//没有附加信息,所以集合里没有这个字符串
else return a[k];
}
};