字典树(Trie树)

前言

你有好多好多字符串,还有好多好多要查询的字符串,你要确定要查询的字符串是否出现过,如果使用暴力搜索,那么肯定爆炸了,那么这样我们该如何进行查找呢?

 如果要存:"abc"、"bc"、"bd"、"cd"的话

 字典树(Trie树)_第1张图片

那么代码怎么写呢?

1.存储

如果用数组存,我们就需要一个二维数组a[n][m]。n点的标号,定义时设为字符串的总长,m指字符类型,定义时设为字符类型总数。

2.添加

首先需要一个记录点编号的ptop,在添加时,先从ROOT,即从a[0]开始找,如果a[查找编号][查找字符编号]存在则继续找,不存在则令其等于++ptop,然后从ptop继续找。

void add(char str[])
{
	int p = 0,end = strlen(str);
	for(int i = 0;i < end;i++)
	{
		if(a[p][turn(str[i])] == 0)
		p = a[p][turn(str[i])] = ++ptop;
		else
		p = a[p][turn(str[i])];
	}
}

3.查找数量

定义一个cnt[n]来记录,如果是前缀就让加入时便cnt[p]++,如果是单词数量便在最后cnt[p]++即可,查找就正常查找。

输出:


int find(char str[])
{
	int end = strlen(str);
	int p = 0;
	for(int i = 0;i < end;i++)
	{
		p = a[p][turn(str[i])];
		if(p == 0)
		return 0;
	}
	return cnt[p];
}	

4.字符转数字

我们需要一个turn函数让字符转成对应的编号

代码:

const int MAXN = 3e6 + 10;

int turn(char c)
{
    if(c >= 'a' && c <= 'z')
    return c - 'a';
    else if(c >= 'A' && c <= 'Z')
    return c - 'A' + 26;
    else
    return c - '0' + 52;
}

struct tiretree{
	int ptop = 0;
	int a[MAXN][70];
	int cnt[MAXN];
	
	void clear()
	{
		for(int i = 1;i <= ptop;i++)
		{
			cnt[i] = 0;
			for(int j = 0;j <= 69;j++)
			a[i][j] = 0;
		}
		ptop = 0;
	}
	
	void add(char str[])
	{
		int p = 0,end = strlen(str);
		for(int i = 0;i < end;i++)
		{
			if(a[p][turn(str[i])] == 0)
			p = a[p][turn(str[i])] = ++ptop;
			else
			p = a[p][turn(str[i])];
			cnt[p]++;
		}
	}
	
	int find(char str[])
	{
		int end = strlen(str);
		int p = 0;
		for(int i = 0;i < end;i++)
		{
			p = a[p][turn(str[i])];
		    if(p == 0)
			return 0;
		}
		return cnt[p];
	}	
}ttree;

你可能感兴趣的:(算法,结构体封装计划,c++,数据结构,算法)