Trie的复习

目的:实现字符串快速检索
每个节点拥有若干个字符指针

空间换时间......

插入Insert
void Insert(char *str)
{
	int len = strlen(str);
	int root = 1;
	for(int k = 0;k < len; k++)
	{
		int ch = str[k] - 'a';
		if(!trie[root][ch]) trie[root][ch] = ++tot;
		root = trie[root][ch];
	}
	end[root] = 1;
}
检索
int check(char *str)
{
	int len = strlen(str), p = 1;
	for(int k = 0;k < len; k++)
	{
		p = trie[p][str[k] - 'a'];
		if(!p) return 0;
	}
	if(end[p]) return 1;
	else 
	{
		end[p] = 1;
		return 2;
	}
}


亦或的作用很多可以和trie树联系起来
这很显然
因为亦或的值可以在tri树上走相反数码
这就直接和亦或的最大最下联系起来了
亦或的性质还有一个
树上两个点的亦或值等于他们到根的亦或值的亦或值 -> *所以直接手动dfs 求出到根的亦或值 就ojbk了
其实并没有什么的......

就看字典树怎么套线段树什么的了 ....

例题 在给定的 NNN 个整数 A1,A2,…,ANA_1,A_2,…,A_NA1,A2,,AN 中选出两个进行异或运算,得到的结果最大是多少?

思路 : 建树直接找相反亦或就OK了

#include<bits/stdc++.h>
using namespace std;
const int max_n = 3100010;

int trie[max_n][2], tot = 1;
int end[max_n];
int A[100010];

void Insert(int x)
{
    int p = 1;
    for(int i = 30;~i; i--)
    {
        int c = (x >> i) & 1;
        if(!trie[p][c]) trie[p][c] = ++ tot;
        p = trie[p][c];
    }
    end[p] = 1;
}

int check(int x)
{
    int p = 1;
    int ans = 0;
    for(int i = 30;~i; i--)
    {
        int c = (x >> i) & 1; 
        int ch = trie[p][c ^ 1];
        if(!ch)
        {
            if(!trie[p][c])
            return ans;
            p = trie[p][c];
            continue;
        }
        ans += pow(2, i);
        p = trie[p][c ^ 1];
    }
    return ans;
}
int main()
{
    int n;
    scanf("%d", &n);
    int a;
    for(int i = 1;i <= n; i++)
    {
        scanf("%d", &A[i]);
        Insert(A[i]);
    }
    int Ans = -1;
    for(int i = 1;i <= n; i++)
    Ans = max(Ans, check(A[i]));
    cout << Ans;
    return 0;
}
    

猜你喜欢

转载自www.cnblogs.com/lanyangs/p/9779964.html