字典树 模板 记录

 

字典树:很强大的数据结构,实现多个字符串的查找、对其个数的纪录以及对其子串的查询。

 

这里讲下建树过程:

 

 准备:MAX 记录总节点数目

char str[1010][50];//输入的字符串集 
int ch[MAX][30];//字典树的实现 
int word[MAX];//记录当前节点下有多少个单词 
int val[MAX];//标记单词节点 
int sz;//节点数 

初始化:

void init()
{
	sz = 1;
	memset(ch[0], 0, sizeof(ch[0]));
	memset(word, 0, sizeof(word));
} 


返回字符的ascll码值:

int idx(char x)
{
	return x - 'a';
}


插入字符串:


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;//是前缀 
} 

判断字符串是否由串集里的两个字符串构成: 假设该字符串分s1,s2两部分,这里只实现s1的查找

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];//最后一个是不是单词节点 
}

大模板:


#include 
#include 
#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];//最后一个是不是单词节点 
}




你可能感兴趣的:(算法与有趣代码--记录,字典树)