概述

Trie 也加字典树,它是一个树形结构。它主要用于处理字符串匹配的数据结构。此外Trie 树也称 前缀树(PrfixTree),主要判断字符串是否是以某个子串开头。

用途

解决在一组字符串集合中快速查找某个字符串的问题。

性质

每个节点至少包含两个基本属性
child:数组或者集合,罗列出每个分支当中包含的所有字符
isEnd 布尔值表示该节点是否为某个字符串的结尾

操作

创建

遍历一遍输入的字符串,对每个字符串的字符进行遍历
从前缀树的根节点开始,将每个字符加入到节点的children字符集当中
如果字符集已经包含了这个字符,跳过
如果当前字符是字符串的最后一个,把当前节点的isEnd标记为真

  1. import java.util.TreeMap;
  2. public class Trie {
  3. private class Node{
  4. public boolean isWord;
  5. public TreeMap<Character,Node> next;
  6. public Node(boolean isWord) {
  7. this.isWord = isWord;
  8. next = new TreeMap<>();
  9. }
  10. }
  11. private Node root;
  12. private int size;
  13. public Trie(){
  14. root = new Node(false);
  15. size = 0;
  16. }
  17. public void add(String word){
  18. Node currNode = root;
  19. for(int i = 0;i<word.length();i++){
  20. char c = word.charAt(i);
  21. if (currNode.next.get(c) ==null){
  22. currNode.next.put(c,new Node(false));
  23. }
  24. currNode = currNode.next.get(c);
  25. }
  26. if (!currNode.isWord){
  27. currNode.isWord = true;
  28. size++;
  29. }
  30. }
  31. }

一个 int 即可存储 26 个字母

  1. class Trie {
  2. class TrieNode {
  3. private int v;
  4. boolean end;
  5. TrieNode[] next = new TrieNode[26];
  6. TrieNode(char ch) {
  7. v = 1 << (ch - 'a');
  8. }
  9. TrieNode add(char ch) {
  10. int k = ch - 'a';
  11. if (next[k] != null) {
  12. next[k].v |= 1 << k;
  13. } else {
  14. next[k] = new TrieNode((ch));
  15. }
  16. return next[k];
  17. }
  18. TrieNode get(char ch) {
  19. return next[ch - 'a'];
  20. }
  21. }
  22. TrieNode root = new TrieNode('a');
  23. /**
  24. * Initialize your data structure here.
  25. */
  26. public Trie() {}
  27. /**
  28. * Inserts a word into the trie.
  29. */
  30. public void insert(String word) {
  31. TrieNode p = root;
  32. for (char c : word.toCharArray()) {
  33. p = p.add(c);
  34. }
  35. p.end = true;
  36. }
  37. /**
  38. * Returns if the word is in the trie.
  39. */
  40. public boolean search(String word) {
  41. TrieNode p = root;
  42. for (char c : word.toCharArray()) {
  43. p = p.get(c);
  44. if (p == null) {
  45. return false;
  46. }
  47. }
  48. return p.end;
  49. }
  50. /**
  51. * Returns if there is any word in the trie that starts with the given prefix.
  52. */
  53. public boolean startsWith(String prefix) {
  54. TrieNode p = root;
  55. for (char c : prefix.toCharArray()) {
  56. p = p.get(c);
  57. if (p == null) {
  58. return false;
  59. }
  60. }
  61. return true;
  62. }
  63. }

搜索

Go语言中字符串前缀判断

  1. func HasPrefix(s, prefix string) bool {
  2. return len(s) >= len(prefix) && s[0:len(prefix)] == prefix
  3. }
  1. // 字典树节点
  2. type TrieNode struct {
  3. children map[interface{}]*TrieNode
  4. isEnd bool
  5. }
  6. // 构造字典树节点
  7. func newTrieNode() *TrieNode {
  8. return &TrieNode{children: make(map[interface{}]*TrieNode), isEnd: false}
  9. }
  10. // 字典树
  11. type Trie struct {
  12. root *TrieNode
  13. }
  14. // 构造字典树
  15. func NewTrie() *Trie {
  16. return &Trie{root: newTrieNode()}
  17. }
  18. // 向字典树中插入一个单词
  19. func (trie *Trie) Insert(word []interface{}) {
  20. node := trie.root
  21. for i := 0; i < len(word); i++ {
  22. _, ok := node.children[word[i]]
  23. if !ok {
  24. node.children[word[i]] = newTrieNode()
  25. }
  26. node = node.children[word[i]]
  27. }
  28. node.isEnd = true
  29. }
  30. // 搜索字典树中是否存在指定单词
  31. func (trie *Trie) Search(word []interface{}) bool {
  32. node := trie.root
  33. for i := 0; i < len(word); i++ {
  34. _, ok := node.children[word[i]]
  35. if !ok {
  36. return false
  37. }
  38. node = node.children[word[i]]
  39. }
  40. return node.isEnd
  41. }
  42. // 判断字典树中是否有指定前缀的单词
  43. func (trie *Trie) StartsWith(prefix []interface{}) bool {
  44. node := trie.root
  45. for i := 0; i < len(prefix); i++ {
  46. _, ok := node.children[prefix[i]]
  47. if !ok {
  48. return false
  49. }
  50. node = node.children[prefix[i]]
  51. }
  52. return true
  53. }