# Handwritten prefix tree

preface:

Remember some problems encountered before, such as how many times words appear in an article? How many times does each word prefix * * appear in an article? An article   ** The word segment appeared several times, and there was an answer after reading the prefix tree.

thinking

1 to build a tree, you need to record the of each node   Number of pass es   End is the number of letters at the end of the word

2. An array is required on the node   26 size is used to store the leaf node of this node

3. When adding words, you need to pass +1 end +1 to the passing nodes. If there is no node, you need to create a new node

4 when deleting   pass -1 end -1 if pass = 0, delete the node

Method design

1)void insert(String str)           To add a string, you can add it repeatedly, one at a time

3)   void delete(String str)           Delete a string, you can delete it repeatedly, one at a time

2)int search(String str)             Query word   How many more characters does a string have in the structure

4)int prefixNumber(String str)   How many query string prefixes are prefixed with STR

4)int prefixNumber(String str)   How many string fragments does the query have   str    for example   hello contains ll count 1

Time complexity

1 add the time complexity as O(n*k), where n is the number of words   K is the length of the word. In fact, because the word is not very long, it can also be ignored as O (n)

2. The deletion time complexity is O(n*k), where n is the number of words   K is the length of the word. In fact, because the word is not very long, it can also be ignored as O (n). Deleting one can be regarded as O (1)

3 query the word O (k), because you can find each character as long as you loop the string

4 same as 3

5. Each node o (n) of the prefix tree needs to be traversed. Here n is the number of nodes of the prefix tree, and O (P) P represents the number of times that the first letter of the string needs to appear in different positions of the word,   Judge whether the nodes starting with this string can satisfy this string, and add the satisfied quantities. Time complexity n * p * k   Because P is equal to k at most, and K is the word length, which will not exceed 10   So time complexity   O(n)

code

```package algorithm;

import com.sun.tools.javac.util.StringUtils;

import java.util.*;

public class trie  {

/**
* Prefix tree node
*/
public static class Node{
//Record the number of passes through this node
public int pass;
//Record the number of text ends at this node
public int end;
//The way to 26 letters
public Node[] nodes;
public Node() {
nodes = new Node;
}
}
/**
* trie
*/
public static class tree{
private Node nodeTree;//Prefix tree root node
//To add a string, you can add it repeatedly, one at a time

public tree() {
this.nodeTree = new Node();
}

public void insert(String str){
if(str.isEmpty()){
return;
}
//Split string
char[] chars = str.toCharArray();
//Get a reference to the tree
Node node = nodeTree;
//Loop each character into the prefix tree
for (int i = 0; i < chars.length; i++) {
//Case range a=97z=122A=65Z=90
//Here, all letters are lowercase by default, and the subscript of the corresponding array is calculated
int subscript = chars[i]-'a';
//If the corresponding letter is empty, add one
if(node.nodes[subscript]==null){
node.nodes[subscript] = new Node();
};
node = node.nodes[subscript];
//Passing++
node.pass++;
}
node.end++;
}
//Delete a string, you can delete it repeatedly, one at a time
public void delete(String str){
if(search(str)==0){
return;
}
if(str.isEmpty()){
return;
}
//Split into char
char[] chars = str.toCharArray();
//Get the reference of node
Node node = nodeTree;
for (int i = 0; i < chars.length; i++) {
//Case range a=97z=122A=65Z=90
//Here, all letters are lowercase by default, and the subscript of the corresponding array is calculated
int subscript = chars[i]-'a';
//If the value after subtraction is equal to 0, delete it directly

if(--node.nodes[subscript].pass==0){
node.nodes[subscript] = null;
return;
}
node = node.nodes[subscript];
}
node.end--;
}
//Query how many times a string appears in the structure, that is, how many times a word appears
public int search(String str) {
Node node = nodeTree;
char[] chars = str.toCharArray();
for (int i = 0; i < chars.length; i++) {
int subscript = chars[i]-'a';
node = node.nodes[subscript];
if (node == null) {
return 0;
}
}
return node.end;
}

// Query how many strings are prefixed with str, that is, the prefix has appeared several times before
public int prefixNumber(String str){
Node node = nodeTree;
char[] chars = str.toCharArray();
for (int i = 0; i < chars.length; i++) {
int subscript = chars[i]-'a';
node = node.nodes[subscript];
if (node == null) {
return 0;
}
}
return node.pass;
}

/**
* Query how many words a string paragraph contains in the previous string, such as hello hi name family Amy. There are three words containing am
* thinking
*  1 Traverse the tree of each layer, find the node starting with the letter a and put it in the queue
*  2 Traverse the beginning of a in the queue to see if it conforms to am, and then accumulate the number of pass es at the point of m
* @param str
* @return
*/
public int searchStr(String str) {
Node node = nodeTree;
char[] chars = str.toCharArray();

//1 first traverse the whole tree, find the one starting with a and put it in the queue

while (nodeQueue.peek()!=null){
Node node1 = nodeQueue.poll();
for (int i = 0; i < 26; i++) {
//Add nodes that are not empty to the queue and continue to traverse to find nodes equal to the first letter
if (node1.nodes[i]!=null) {
//Determine whether it is equal to the first letter
//Put it in the queue with the first letter and wait for traversal to find out how many match
}
//Put it in the search queue and continue to find the node starting with the first letter
}
}
}
//2 see if all the words beginning with the first letter match the following letters
int num = 0;//Accumulated letters
while (nodeStrQueue.isEmpty()){
Node node1 = nodeStrQueue.poll();
if(node1==null){

}
for (int i = 1; i < chars.length; i++) {
int subscript = chars[i] - 'a';
//Find the next character
node1 = node1.nodes[subscript];
//If you don't stop searching, exit the node to search the character segment of the char array
if (node1 == null) {
break;
}
//If the last letter node is currently found and found
if (i == chars.length-1) {
//Cumulative occurrences of current node
num+=node1.pass;
}
}
}
return num;
}

}
// =========================Test code for prefix tree
// for test
public static String generateRandomString(int strLen) {
char[] ans = new char[(int) (Math.random() * strLen) + 1];
for (int i = 0; i < ans.length; i++) {
int value = (int) (Math.random() * 6);
ans[i] = (char) (97 + value);
}
return String.valueOf(ans);
}

// for test
public static String[] generateRandomStringArray(int arrLen, int strLen) {
String[] ans = new String[(int) (Math.random() * arrLen) + 1];
for (int i = 0; i < ans.length; i++) {
ans[i] = generateRandomString(strLen);
}
return ans;
}
public static class Right {

private HashMap<String, Integer> box;

public Right() {
box = new HashMap<>();
}

public void insert(String word) {
if (!box.containsKey(word)) {
box.put(word, 1);
} else {
box.put(word, box.get(word) + 1);
}
}

public void delete(String word) {
if (box.containsKey(word)) {
if (box.get(word) == 1) {
box.remove(word);
} else {
box.put(word, box.get(word) - 1);
}
}
}

public int search(String word) {
if (!box.containsKey(word)) {
return 0;
} else {
return box.get(word);
}
}

public int prefixNumber(String pre) {
int count = 0;
for (String cur : box.keySet()) {
if (cur.startsWith(pre)) {
count += box.get(cur);
}
}
return count;
}
}
// =========================Test code for prefix tree
public static void main(String[] args) {

tree trie = new tree();
trie.insert("aaa");
trie.insert("bbb");
trie.insert("cc");

trie.delete("aaa");
trie.delete("bbb");
trie.delete("cc");

//Find entire single
trie.insert("hi");
trie.insert("hi");
trie.insert("hello");
trie.insert("mama");
System.out.println("hi Occurred:"+trie.search("hi"));
System.out.println("hello Occurred:"+trie.search("hello"));
System.out.println("ma: "+trie.search("ma"));

//Find prefix
System.out.println("ll Occurred:"+trie.search("ll"));
System.out.println("h Occurred:"+trie.search("h"));
System.out.println("hi Occurred:"+trie.search("hi"));
System.out.println("ma Occurred:"+trie.search("ma"));

//find paragraph
trie.insert("myhi");
trie.insert("ahid");
System.out.println("hi Occurred:"+trie.searchStr("hi"));
System.out.println("ll Occurred:"+trie.searchStr("ll"));

/***
* Logarithm in video
*/
int arrLen = 100;
int strLen = 20;
int testTimes = 100000;
for (int i = 0; i < testTimes; i++) {
String[] arr = generateRandomStringArray(arrLen, strLen);
tree trie1 = new tree();
Right right = new Right();
for (int j = 0; j < arr.length; j++) {
double decide = Math.random();
if (decide < 0.25) {
trie1.insert(arr[j]);
right.insert(arr[j]);
} else if (decide < 0.5) {
trie1.delete(arr[j]);
right.delete(arr[j]);
} else if (decide < 0.75) {
int ans1 = trie1.search(arr[j]);
int ans3 = right.search(arr[j]);
if (ans1 !=  ans3) {
System.out.println("Oops!");
}
} else {
int ans1 = trie1.prefixNumber(arr[j]);
int ans3 = right.prefixNumber(arr[j]);
if (ans1 != ans3) {
System.out.println("Oops!");
}
}
}
}
System.out.println("finish!");

}
}
```

Tags: Algorithm

Posted on Fri, 29 Oct 2021 05:26:40 -0400 by DexterMorgan