Tree dp basics - dictionary tree (simplified version)

The concept of dictionary tree

The model is a multi-fork tree, also known as a prefix tree. If there is no storage character between nodes, it means that there is no such string. The main function is to deal with the redundancy of strings with the same prefix, which is also a tree-type dynamic programming. Foundation

The basic model of dictionary tree

insert image description hereThe strings stored here are in, te, to

code section

This is just a simple function of inserting and querying. The storage tree is also a two-dimensional array, and only lowercase letters are stored.

1. Initialize the required variables

A two-dimensional array trie[i][j], a value of 0 indicates that the character is not initialized, i represents the current node number, j represents the character number of the target node
A one-dimensional array color[i], i represents the node number, and the color of The value is 0 or 1, and 1 represents a leaf node, because when we query a string, only when we reach the leaf node can we show that the string has been stored before.

const int MAX_NODE=1000000;	//总结点最大数量 
const int CHARSET=26;		//字典树且都为小写字母 
int trie[MAX_NODE][CHARSET]={
    
    0};	//0表示该节点没被添加过
int color[MAX_NODE]={
    
    0};		//对每个节点进行标记 1为叶子节点
int k=1;	//记录节点个数以及标记当前节点的
2. Insert function

Insert a string into the dictionary tree. When the current character does not exist, we need to insert the character, and change the value of the trie node to the number of the current node plus one, and set the color to 1 at the position of the last node

void insert(string w)		//增加节点 
{
    
    
	int len=w.length();
	int p=0;
	for(int i=0;i<len;i++)
	{
    
    
		int c=w[i]-'a';		//字母转换成数字
		if(!trie[p][c])		//如果当前节点没有到该节点的路径就添加 
		{
    
    
			trie[p][c]=k;
			++k; 
		} 
		p=trie[p][c];		//遍历下一个 
	}
	
	color[p]=1;		//标记叶子节点 
}
3. Query function

Query character by character. If the current character to be queried has a node value of 0, it means that the string has not been inserted before and returns false directly. Finally, after the entire string to be queried is judged, it is necessary to judge whether the reached point is a leaf node.

int search(string s)		//查找节点 
{
    
    
	int len=s.length();
	int p=0;
	for(int i=0;i<len;i++)
	{
    
    
		int c=s[i]-'a';
		if(!trie[p][c])	return false;
		p=trie[p][c];
	}
	
	return color[p]==1;		//能找到该节点且该节点必须是叶子节点		
} 

full code

#include <bits/stdc++.h>
using namespace std;

const int MAX_NODE=1000000;	//总结点最大数量 
const int CHARSET=26;		//字典树且都为小写字母 
int trie[MAX_NODE][CHARSET]={
    
    0};	//0表示该节点没被添加过
int color[MAX_NODE]={
    
    0};		//对每个节点进行标记 1为叶子节点
int k=1;	//记录节点个数以及标记当前节点的 

void insert(string w)		//增加节点 
{
    
    
	int len=w.length();
	int p=0;
	for(int i=0;i<len;i++)
	{
    
    
		int c=w[i]-'a';		//字母转换成数字
		if(!trie[p][c])		//如果当前节点没有到该节点的路径就添加 
		{
    
    
			trie[p][c]=k;
			++k; 
		} 
		p=trie[p][c];		//遍历下一个 
	}
	
	color[p]=1;		//标记叶子节点 
} 

int search(string s)		//查找节点 
{
    
    
	int len=s.length();
	int p=0;
	for(int i=0;i<len;i++)
	{
    
    
		int c=s[i]-'a';
		if(!trie[p][c])	return false;
		p=trie[p][c];
	}
	
	return color[p]==1;		//能找到该节点且该节点必须是叶子节点		
} 

int main (void)
{
    
    
	int strcnt,searchcnt;		//插入字符串数量和查询字符串的数量
	cout<<"输入需要插入的字符串数量:";
	cin>>strcnt;
	vector<string> str(strcnt);		//插入的字符串数组

	cout<<"下面请输入"<<strcnt<<"个字符串:\n"; 
	for(int i=0;i<strcnt;i++)
	{
    
    
		cin>>str[i];
		insert(str[i]); 
	} 
	
	
	while(1)
	{
    
    
		string tmp;
		cout<<"输入需要查询的小写字母组成的字符串(输入Q退出)\n";
		cin>>tmp;
		if(tmp=="Q")
			return 0;
		else
		{
    
    
			if(search(tmp))
				cout<<"YES\n";
			else
				cout<<"NO\n";
		}	
	} 
	
	return 0;
}
running result

insert image description here

Summarize

Personally, I feel that the dictionary tree (prefix tree) is a memorized method for processing string algorithm problems, which saves the step of repeatedly processing the same prefix of a string.

Guess you like

Origin blog.csdn.net/weixin_46035615/article/details/123845200