Trie introductory sample question summary

Trie (dictionary tree) is a multi-tree structure for fast retrieval of strings. Each node of Trie has several character pointers. If a character c is scanned during insertion or retrieval, it will follow the c character pointer of the current node to the node pointed to by the pointer.
Trie structure is a typical data structure that exchanges space for time. Its space complexity is O (NC), where N represents the number of nodes, and C represents the size of the character set.
One:
Example of string processing : prefix statistics
Question meaning: given n strings, then m queries are asked one string T each time, and how many strings in s1~sn are his prefix
ideas: When inserting a string, the number of strings ending with the current node ++ before the insertion is completed, and then asking the T string from beginning to end.

#include <bits/stdc++.h>
// trie 模板
using namespace std;
typedef long long ll;
const int MAXN = 1e6+7;
const int N = 5e5+7;
char str[MAXN];
int t[N][26],cnt[N],idx;//cnt数组保存以当前节点为结尾的字符串有几个
void insert(char *s)
{
    
    
	int len = strlen(s);
	int p = 0;
	for(int i = 0;i < len;i ++){
    
    
		if(!t[p][s[i]-'a']) t[p][s[i]-'a'] = ++idx;//这个idx就相当有我这个虚拟数组的分配的标号
		p = t[p][s[i]-'a'];
	}
	cnt[p]++;//当前大小++
}

int query(char *s)
{
    
    
	int len = strlen(s),p = 0,ans = 0;
	for(int i = 0;i < len;i ++){
    
    
		p = t[p][s[i]-'a'];
		if(!p) break;
		ans += cnt[p];
	}
	return ans;
}

int main()
{
    
    
	int n,m;
	scanf("%d%d",&n,&m);
	while(n--){
    
    
		scanf("%s",str);
		insert(str);
	}
	while(m--){
    
    
		scanf("%s",str);
		printf("%d\n",query(str));
	}
	return 0;
}

POJ3630

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std;

typedef long long ll;
const int MAXN = 5e5+7;
string str[MAXN];
int trie[MAXN][17],idx,vis[MAXN];

bool insert(string s)
{
    
    
	int p = 0,len = s.size();
	for(int i = 0;i < len;i ++){
    
    
		int ch = s[i]-'0';
		if(!trie[p][ch]) trie[p][ch] = ++idx;
		if(vis[p]) return true;
		p = trie[p][ch];
	}
	vis[p] = 1;
	return false;
}

bool cmp(string a,string b)
{
    
    
	int lena = a.size(),lenb = b.size();
	return lena < lenb;
}

int main()
{
    
    
	int t;
	scanf("%d",&t);
	while(t--){
    
    
		int n;
		memset(vis,0,sizeof(vis));
		memset(trie,0,sizeof(trie));
		scanf("%d",&n);
		for(int i = 1;i <= n;i ++){
    
    
			cin>>str[i];
		}
		sort(str+1,str+1+n,cmp);
		//for(int i = 1;i <= n;i ++) cout<<str[i]<<endl;
		int flag = 0;
		for(int i = 1;i <= n;i ++){
    
    
			if(insert(str[i])){
    
    
				flag = 1;
				break;
			}
		}
		if(flag)puts("NO");
		else puts("YES");
	}
	return 0;
}

Two: Trie can not only operate on strings, but also on integers, because decimal numbers can be converted to 01 strings in binary, so trie is often used to solve the XOR operation of integers.
Example: Maximum XOR Sum
Question meaning: Given n numbers, find the maximum value that can be obtained by combining XOR between them.
Idea: Think of each number as a 01 binary string, and use trie to store the 01 string of each integer. When querying, you only need the exclusive OR and the maximum. The binary number corresponding to each bit is as different as possible. Therefore, when querying, the best solution is to go in a direction different from the current bit value. If different directions do not exist, go in the same direction.

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int MAXN = 1e5+7;
const int N = 5e5+7;
int trie[31*MAXN][2],idx;
int a[MAXN];
// 这道题就说明 trie 不仅可以 操作字符串 同时还可以对二进制状态下的01串进行操作
void insert(int x)
{
    
    
	int p = 0;
	for(int i = 30;i >= 0;i --){
    
    
		int ch = x>>i & 1;
		if(!trie[p][ch])
			trie[p][ch] = ++idx;
		p = trie[p][ch];
	}
}

int search(int x){
    
    
	int p = 0,sum = 0,cnt = 0;
	for(int i = 30;i >= 0;i --){
    
    
		int ch = x>>i & 1;// 二进制下的取每一位的方法
		if(trie[p][!ch]){
    
    
			p = trie[p][!ch];
			sum += (1<<i)*(!ch);
		}
		else if(trie[p][ch]){
    
    
			p = trie[p][ch];
			sum += (1<<i)*ch;
		}
		else break;
	}
	return sum;
}

int main()
{
    
    
	int n;
	scanf("%d",&n);
	for(int i = 1;i <= n;i ++){
    
    
		scanf("%d",&a[i]);
		insert(a[i]);
	}
	int ans = 0;

	for(int i = 1;i <= n;i ++){
    
    
		ans=max(ans,search(a[i])^a[i]);
		//printf("%d\n",search(a[i]));
	}
	printf("%d\n",ans);
	return 0;
}

This
question of HDU5536 uses the delete operation of trie.
Find a given number of n.
Find three different numbers so that the value of (a[i]+a[j])^ a[k] is the largest
because of the requirement of this question The three numbers cannot be the same, so you need to delete i and j from the trie before querying. This can be done with a flag array mark, ++ when inserting, and – when deleting.

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int MAXN = 1e3+100;
int a[MAXN];
//因为要保证 三个数不能有相同的 因此这次要用到 trie树的删除结构
int trie[MAXN*31][2],idx,val[MAXN*31];//val数组保存存入的值
int flag[MAXN*31];

void insert(int x)
{
    
    
	int p = 0;
	for(int i = 30;i >= 0;i --){
    
    
		int u = x>>i & 1;
		if(!trie[p][u]) trie[p][u] = ++idx;
		p = trie[p][u];
		flag[p]++;//和后面的删除对着
	}
	val[p] = x;
}

void del(int x)//删除操作 不同就是 查询之前 先把 si,sj删除 然后再查询 查询完后 再插入si,sj
{
    
    
	int p = 0;
	for(int i = 30;i >= 0;i --){
    
    
		int u = x>>i & 1;
		p = trie[p][u];
		flag[p]--;
	}
}

int query(int x)
{
    
    
	int p = 0;
	for(int i = 30;i >= 0;i --){
    
    
		int u = x>>i & 1;
		p = (flag[trie[p][!u]]?trie[p][!u]:trie[p][u]);
	}
	return val[p]^x;
}

int main()
{
    
    
	int t;
	scanf("%d",&t);
	while(t--){
    
    
		memset(flag,0,sizeof(flag));
		memset(val,0,sizeof(val));
		memset(trie,0,sizeof(trie));
		idx = 0;
		int n;
		scanf("%d",&n);
		for(int i = 1;i <= n;i ++){
    
    
			scanf("%d",&a[i]);
			insert(a[i]);
		}
		int ans = 0;
		for(int i = 1;i < n;i ++){
    
    
			for(int j = i+1;j <= n;j ++){
    
    
				del(a[i]);
				del(a[j]);
				ans =  max(ans,query(a[i]+a[j]));
				insert(a[i]);
				insert(a[j]);
			}
		}
		printf("%d\n",ans);
	}	
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_45672411/article/details/107565836