字典树:很强大的数据结构,实现多个字符串的查找、对其个数的纪录以及对其子串的查询。
连接:http://blog.csdn.net/chenzhenyu123456/article/details/46490539
这里讲下建树过程:
准备:MAX 记录总节点数目
[cpp] view plaincopy
- char str[1010][50];//输入的字符串集
- int ch[MAX][30];//字典树的实现
- int word[MAX];//记录当前节点下有多少个单词
- int val[MAX];//标记单词节点
- int sz;//节点数
初始化:
[cpp] view plaincopy
- void init()
- {
- sz = 1;
- memset(ch[0], 0, sizeof(ch[0]));
- memset(word, 0, sizeof(word));
- }
返回字符的ascll码值:
[cpp] view plaincopy
- int idx(char x)
- {
- return x - ‘a‘;
- }
插入字符串:
[cpp] view plaincopy
- void insert(char *s)
- {
- int i, j, len = strlen(s);
- int u = 0;//根节点开始
- for(i = 0; i < len; i++)
- {
- int c = idx(s[i]);
- if(!ch[u][c])//当前节点不存在
- {
- memset(ch[sz], 0, sizeof(ch[sz]));//初始化新节点
- val[sz] = 0;
- ch[u][c] = sz++; //节点数增一
- }
- u = ch[u][c];
- word[u]++;//单词数加一
- }
- val[u] = 1;//标记单词节点
- }
查找以字符串s为前缀的字符串 在字符串集中有多少个
[cpp] view plaincopy
- int findnum(char *s)//查询以该s为前缀的字符串有多少个
- {
- int i, j, l = strlen(s);
- int u = 0;
- for(i = 0; i < l; i++)
- {
- int c = idx(s[i]);
- if(!ch[u][c]) return 0;//不存在
- u = ch[u][c];
- }
- return word[u];
- }
查找并输出字符串在串集里面唯一确定的最短前缀 :
[cpp] view plaincopy
- void findprefix(char *s)
- {
- int i, j, len = strlen(s);
- int u = 0;
- for(i = 0; i < len; i++)
- {
- int c = idx(s[i]);
- u = ch[u][c];//继续查找
- printf("%c", s[i]);
- if(word[u] == 1)//节点下只有一个单词
- return ;
- }
- }
判断该字符串是不是串集里某个字符串前缀 :
[cpp] view plaincopy
- bool judgeprefix(char *s)
- {
- int i, j, len = strlen(s);
- int u = 0;
- for(i = 0; i < len; i++)
- {
- int c = idx(s[i]);
- u = ch[u][c];//继续查找
- if(word[u] == 1)//不是任何字符串的前缀
- return true;
- }
- return false;//是前缀
- }
判断字符串是否由串集里的两个字符串构成: 假设该字符串分s1,s2两部分,这里只实现s1的查找
[cpp] view plaincopy
- bool finds(char *s)
- {
- int i, j, len = strlen(s);
- int u = 0;
- for(i = 0; i < len; i++)
- {
- int c = idx(s[i]);
- if(!ch[u][c])//不存在节点
- return false;
- u = ch[u][c];
- }
- return val[u];//最后一个是不是单词节点
- }
大模板:
[cpp] view plaincopy
- #include <cstdio>
- #include <cstring>
- #define MAX 50000+10
- using namespace std;
- char str[1010][50];//输入的字符串集
- int ch[MAX][30];//字典树的实现
- int word[MAX];//记录当前节点下有多少个单词
- int val[MAX];//标记单词节点
- int sz;//节点数
- int idx(char x)
- {
- return x - ‘a‘;
- }
- void init()
- {
- sz = 1;
- memset(ch[0], 0, sizeof(ch[0]));
- memset(word, 0, sizeof(word));
- }
- void insert(char *s)
- {
- int i, j, len = strlen(s);
- int u = 0;//根节点开始
- for(i = 0; i < len; i++)
- {
- int c = idx(s[i]);
- if(!ch[u][c])//当前节点不存在
- {
- memset(ch[sz], 0, sizeof(ch[sz]));//初始化新节点
- val[sz] = 0;
- ch[u][c] = sz++; //节点数增一
- }
- u = ch[u][c];
- word[u]++;//单词数加一
- }
- val[u] = 1;//标记单词节点
- }
- //查找以字符串s为前缀的字符串 在字符串集中有多少个
- int findnum(char *s)//查询以该s为前缀的字符串有多少个
- {
- int i, j, l = strlen(s);
- int u = 0;
- for(i = 0; i < l; i++)
- {
- int c = idx(s[i]);
- if(!ch[u][c]) return 0;//不存在
- u = ch[u][c];
- }
- return word[u];
- }
- //查找并输出字符串在串集里面唯一确定的最短前缀
- void findprefix(char *s)
- {
- int i, j, len = strlen(s);
- int u = 0;
- for(i = 0; i < len; i++)
- {
- int c = idx(s[i]);
- u = ch[u][c];//继续查找
- printf("%c", s[i]);
- if(word[u] == 1)//节点下只有一个单词
- return ;
- }
- }
- //判断该字符串是不是串集里某个字符串前缀
- bool judgeprefix(char *s)
- {
- int i, j, len = strlen(s);
- int u = 0;
- for(i = 0; i < len; i++)
- {
- int c = idx(s[i]);
- u = ch[u][c];//继续查找
- if(word[u] == 1)//不是任何字符串的前缀
- return true;
- }
- return false;//是前缀
- }
- //判断字符串是否由串集里的两个字符串构成:假设该字符串分两部分,这里只实现一部分的查找
- bool finds(char *s)
- {
- int i, j, len = strlen(s);
- int u = 0;
- for(i = 0; i < len; i++)
- {
- int c = idx(s[i]);
- if(!ch[u][c])//不存在节点
- return false;
- u = ch[u][c];
- }
- return val[u];//最后一个是不是单词节点
- }
时间: 2024-10-11 10:09:54