Tires tree data structure

Tries

Tries tree is a data structure used to efficiently store and find string sets

for example

The following five strings Tries as follows
abbcca
adacaa
bcc
bccac

And mark the word node at the end of each character (indicating that there are words that have ended at this point)

It can efficiently find whether a string appears in the collection and the number of occurrences
 for example
 lookup	"bcc"
root -> b -> c -> c(Tag found successfully)

lookup	"abbc"
root -> a -> b -> b -> c	(here c Node is not marked and does not exist to c Ending word)	


Trie string statistics

Title Description

Maintain a string collection and support two operations:

I x inserts a string x into the set;
Q x asks how many times a string appears in the set.
There are N operations in total. The total length of the input string does not exceed 105. The string contains only lowercase English letters.

Input format

The first line contains the integer N, which represents the operand.

Next N lines, each line contains an operation instruction, which is one of I x or Q x.

Output format

For each query instruction Q x, an integer is output as the result, indicating the number of times x appears in the set.

One line for each result.

Data range

1 ≤ N ≤ 2 ∗ 1 0 4 1≤N≤2∗10^4 1≤N≤2∗104

Input example:

5
I abc
Q abc
Q ab
I ab
Q ab

Output example:

1
0
1

Problem solution

The key to the creation and search of Tries tree is two functions and, s o n [ N ] [ 26 ] , i d x , c n t [ N ] son[N][26], idx, cnt[N] son[N][26],idx,cnt[N]

s [ i ] [ j ] s[i][j] s[i][j] means the child node of the current i-th node and stores the node address of the j-th letter (understood as address)

c n t [ i ] cnt[i] cnt[i] the number of times the word in the ith node appears as the end ()

i d x idx idx creates a new node subscript (creates a new analog address, which is understood to be equivalent to a new address)

Note: the root node = = 0 is empty

code

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

const int N = 10010;

int son[N][26], idx, cnt[N];

void insert(char str[])
{
    int p = 0;
    for (int i = 0; str[i]; i ++)
    {
        int u = str[i] - 'a';				//Get letter mapping
        if (!son[p][u]) son[p][u] = ++ idx;     //If the address subscript is empty, it means that it has not been created, and duplicate creation is prevented
        p = son[p][u];							// p is the traversal pointer to the child node just created
    }

    cnt[p] ++;				//Mark the node at the end of the last word 	 p is the pointer
}

int query(char str[])
{
    int p = 0;
    for (int i = 0; str[i]; i ++)
    {
        int u = str[i] - 'a';
        if (!son[p][u])     return 0;	//If the letter is not changed in the child node that the current p points to, the string does not exist
        p = son[p][u];		
    }

    return cnt[p];
}
int main()
{
    int n;
    cin >> n;

    while (n -- )
    {
        char op[2], str[N];
        scanf("%s%s",op, str);
        if (op[0] == 'I')  insert(str);
        else    printf("%d\n", query(str));
    }
    return 0;
}

Maximum XOR pair

Title Description

In the given N integers A 1 , A 2 ... ... , A N A_1,A_2......, A_N Select two from A1, A2... And AN to perform xor operation. What is the maximum result?

Input format

Enter an integer N on the first line.

Enter N integers on the second line A 1 ~ A N A_1~A_N A1​~AN​.

Output format

Output an integer representing the answer.

Data range

1 ≤ N ≤ 1 0 5 , 1≤N≤10^5, 1≤N≤105,
0 ≤ A i < 2 31 0≤A_i<2^{31} 0≤Ai​<231

Input example:

3
1 2 3

Output example:

3

Problem solution

First, violent practices O ( n 2 ) O(n^2) O(n2)

for (int i = 0; i < n; i ++)
    for (int j = 0; j <= i; i++)
    {
        ans = max(ans,a[i] ^ a[j])
    }

We try to optimize the inner loop

The meaning of inner loop: find a number and a [ i ] a[i] a[i] maximum XOR value

First of all, the XOR value is the largest, that is, starting from the highest bit, the binary digits are different, and each bit is like this. The last number found must be the number with the largest XOR a[i] value

After we convert a number into binary, we use the Tries tree to save it

When searching, use res to record the corresponding decimal

After optimization, the inner layer from O ( n ) O(n) The time complexity of O(n) becomes the worst at the constant level O ( 31 ) O(31) O(31)

The overall complexity is close to O ( n l o g n ) O(nlog_n) O(nlogn​)

code

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

const int N = 100010;

int son[N*31][2], idx;
int a[N];

void insert(int x)
{
    int p = 0;
    for (int i = 30; i >= 0; i --)
    {
        int u = x >> i & 1;
        if (!son[p][u])     son[p][u] = ++ idx;
        p = son[p][u];
    }
}

int query(int x)
{
    int p = 0, res = 0;
    for (int i = 30; i >= 0; i --)
    {
        int u = x >> i & 1;
        if (son[p][!u])         //If XOR wants to find a child node with different digits, judge the child node of the node first! Whether u exists
        {
            res = res * 2 + !u;
            p = son[p][!u];
        }
        else
        {
            res = res * 2 + u;
            p = son[p][u];
        }
    }
    
    return res ^ x;
}
int main()
{
   int n, ans = 0;
   cin >> n;
   
   for (int i = 0; i < n;  i++)     scanf("%d", &a[i]);
   
   for (int i = 0; i < n; i ++)
   {
       insert(a[i]);
       ans = max(ans,query(a[i]));
   }
    
    cout << ans;
    return 0;
}

Tags: Algorithm data structure

Posted on Fri, 01 Oct 2021 17:12:14 -0400 by airdee