一.字典树解决了什么问题?
字典树对于查找字符串很快,尤其是判断一个字符串是否为另一个字符串的前缀,以及前缀的长度。
二.字典树的建立
字典树的链表版本很好理解。
首先定义一个struct
struct node { node *nexta[26]; int countx;//有相同前缀的字符出现的次数 node() { memset(nexta,NULL,sizeof(nexta)); countx = 0; } };字符串的每个字符都建在树里,如果这个字符的下一个之前没有存在就建一个新的
node *p,*root = new node(); void build(char a[]) { p = root; int t,l = strlen(a); for(int i = 0;i < l; i++) { t = a[i] - 'a'; if(p->nexta[t] == NULL) { p->nexta[t] = new node(); } p = p -> nexta[t]; p->countx ++; }数组版:
struct node { int nexta[26]; int countx; }f[1000000]; void init(int a)//新增函数 { memset(f[a].nexta,-1,sizeof(f[a].nexta)); f[a].countx = 0; } int cnt = 1; void build(char a[]) { int p = 0; int t,l = strlen(a); for(int i = 0;i < l; i++) { t = a[i] - 'a'; if(f[p].nexta[t] == -1) { f[p].nexta[t] = cnt; init(cnt); cnt++; } p = f[p].nexta[t]; f[p].countx ++; } }
这里的树根都是不存信息的
三.字典树的查找
如果一个字符串还没找到头,指针就指向空了,说明没有该字符串
指针版本:
int findx(char a[]) { p = root; int t,l = strlen(a); for(int i = 0; i < l; i ++) { t = a[i] - 'a'; if(p->nexta[t] == NULL) { return 0;//走到头了 } p = p ->nexta[t]; } return p -> countx; }数组版本
int findx(char a[]) { int k = 0; int t,l = strlen(a); for(int i = 0; i < l; i ++) { t = a[i] - 'a'; k = f[k].nexta[t]; if(k == -1) return 0; } return f[k].countx; }