← Back

Trie (Prefix Tree)

Store words by shared prefixes for fast insert and lookup.

1 / 1
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
type Trie struct {
    children [26]*Trie
    end      bool
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
type Trie struct {
    children [26]*Trie
    end      bool
}

    // Start at the root and walk down one letter at a time.
        // Map the letter to a slot 0..25.
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
type Trie struct {
    children [26]*Trie
    end      bool
}

func (t *Trie) Insert(word string) {
    // Start at the root and walk down one letter at a time.
    node := t
    for _, ch := range word {
        // Map the letter to a slot 0..25.
        i := ch - 'a'
    }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
type Trie struct {
    children [26]*Trie
    end      bool
}

func (t *Trie) Insert(word string) {
    // Start at the root and walk down one letter at a time.
    node := t
    for _, ch := range word {
        // Map the letter to a slot 0..25.
        i := ch - 'a'

        // If this letter has never been seen from here, grow a new branch.

        // Descend into that child and continue with the next letter.
    }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
type Trie struct {
    children [26]*Trie
    end      bool
}

func (t *Trie) Insert(word string) {
    // Start at the root and walk down one letter at a time.
    node := t
    for _, ch := range word {
        // Map the letter to a slot 0..25.
        i := ch - 'a'

        // If this letter has never been seen from here, grow a new branch.
        if node.children[i] == nil {
            node.children[i] = &Trie{}
        }

        // Descend into that child and continue with the next letter.
        node = node.children[i]
    }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
type Trie struct {
    children [26]*Trie
    end      bool
}

func (t *Trie) Insert(word string) {
    // Start at the root and walk down one letter at a time.
    node := t
    for _, ch := range word {
        // Map the letter to a slot 0..25.
        i := ch - 'a'

        // If this letter has never been seen from here, grow a new branch.
        if node.children[i] == nil {
            node.children[i] = &Trie{}
        }

        // Descend into that child and continue with the next letter.
        node = node.children[i]
    }

    // We've placed every letter; mark this node as the end of a real word.
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
type Trie struct {
    children [26]*Trie
    end      bool
}

func (t *Trie) Insert(word string) {
    // Start at the root and walk down one letter at a time.
    node := t
    for _, ch := range word {
        // Map the letter to a slot 0..25.
        i := ch - 'a'

        // If this letter has never been seen from here, grow a new branch.
        if node.children[i] == nil {
            node.children[i] = &Trie{}
        }

        // Descend into that child and continue with the next letter.
        node = node.children[i]
    }

    // We've placed every letter; mark this node as the end of a real word.
    node.end = true
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
type Trie struct {
    children [26]*Trie
    end      bool
}

func (t *Trie) Insert(word string) {
    // Start at the root and walk down one letter at a time.
    node := t
    for _, ch := range word {
        // Map the letter to a slot 0..25.
        i := ch - 'a'

        // If this letter has never been seen from here, grow a new branch.
        if node.children[i] == nil {
            node.children[i] = &Trie{}
        }

        // Descend into that child and continue with the next letter.
        node = node.children[i]
    }

    // We've placed every letter; mark this node as the end of a real word.
    node.end = true
}

    // Follow the same path the letters describe.

        // A missing branch means the word was never inserted.

    // The path exists — but it's only a match if a word actually ended here
    // (otherwise "app" would wrongly match when only "apple" was inserted).
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
type Trie struct {
    children [26]*Trie
    end      bool
}

func (t *Trie) Insert(word string) {
    // Start at the root and walk down one letter at a time.
    node := t
    for _, ch := range word {
        // Map the letter to a slot 0..25.
        i := ch - 'a'

        // If this letter has never been seen from here, grow a new branch.
        if node.children[i] == nil {
            node.children[i] = &Trie{}
        }

        // Descend into that child and continue with the next letter.
        node = node.children[i]
    }

    // We've placed every letter; mark this node as the end of a real word.
    node.end = true
}

func (t *Trie) Search(word string) bool {
    // Follow the same path the letters describe.
    node := t
    for _, ch := range word {
        i := ch - 'a'

        // A missing branch means the word was never inserted.
        if node.children[i] == nil {
            return false
        }
        node = node.children[i]
    }

    // The path exists — but it's only a match if a word actually ended here
    // (otherwise "app" would wrongly match when only "apple" was inserted).
    return node.end
}
# Each node has one child slot per lowercase letter, plus a flag marking
# whether a complete word ends here. Shared prefixes share the same path.
class Trie:
    def __init__(self):
        self.children = [None] * 26
        self.end = False
# Each node has one child slot per lowercase letter, plus a flag marking
# whether a complete word ends here. Shared prefixes share the same path.
class Trie:
    def __init__(self):
        self.children = [None] * 26
        self.end = False

    # Start at the root and walk down one letter at a time.
        # Map the letter to a slot 0..25.
# Each node has one child slot per lowercase letter, plus a flag marking
# whether a complete word ends here. Shared prefixes share the same path.
class Trie:
    def __init__(self):
        self.children = [None] * 26
        self.end = False
    def insert(self, word):
        # Start at the root and walk down one letter at a time.
        node = self
        for ch in word:
            # Map the letter to a slot 0..25.
            i = ord(ch) - ord('a')
# Each node has one child slot per lowercase letter, plus a flag marking
# whether a complete word ends here. Shared prefixes share the same path.
class Trie:
    def __init__(self):
        self.children = [None] * 26
        self.end = False
    def insert(self, word):
        # Start at the root and walk down one letter at a time.
        node = self
        for ch in word:
            # Map the letter to a slot 0..25.
            i = ord(ch) - ord('a')

            # If this letter has never been seen from here, grow a new branch.

            # Descend into that child and continue with the next letter.
# Each node has one child slot per lowercase letter, plus a flag marking
# whether a complete word ends here. Shared prefixes share the same path.
class Trie:
    def __init__(self):
        self.children = [None] * 26
        self.end = False
    def insert(self, word):
        # Start at the root and walk down one letter at a time.
        node = self
        for ch in word:
            # Map the letter to a slot 0..25.
            i = ord(ch) - ord('a')

            # If this letter has never been seen from here, grow a new branch.
            if node.children[i] is None:
                node.children[i] = Trie()

            # Descend into that child and continue with the next letter.
            node = node.children[i]
# Each node has one child slot per lowercase letter, plus a flag marking
# whether a complete word ends here. Shared prefixes share the same path.
class Trie:
    def __init__(self):
        self.children = [None] * 26
        self.end = False
    def insert(self, word):
        # Start at the root and walk down one letter at a time.
        node = self
        for ch in word:
            # Map the letter to a slot 0..25.
            i = ord(ch) - ord('a')

            # If this letter has never been seen from here, grow a new branch.
            if node.children[i] is None:
                node.children[i] = Trie()

            # Descend into that child and continue with the next letter.
            node = node.children[i]

        # We've placed every letter; mark this node as the end of a real word.
# Each node has one child slot per lowercase letter, plus a flag marking
# whether a complete word ends here. Shared prefixes share the same path.
class Trie:
    def __init__(self):
        self.children = [None] * 26
        self.end = False
    def insert(self, word):
        # Start at the root and walk down one letter at a time.
        node = self
        for ch in word:
            # Map the letter to a slot 0..25.
            i = ord(ch) - ord('a')

            # If this letter has never been seen from here, grow a new branch.
            if node.children[i] is None:
                node.children[i] = Trie()

            # Descend into that child and continue with the next letter.
            node = node.children[i]

        # We've placed every letter; mark this node as the end of a real word.
        node.end = True
# Each node has one child slot per lowercase letter, plus a flag marking
# whether a complete word ends here. Shared prefixes share the same path.
class Trie:
    def __init__(self):
        self.children = [None] * 26
        self.end = False
    def insert(self, word):
        # Start at the root and walk down one letter at a time.
        node = self
        for ch in word:
            # Map the letter to a slot 0..25.
            i = ord(ch) - ord('a')

            # If this letter has never been seen from here, grow a new branch.
            if node.children[i] is None:
                node.children[i] = Trie()

            # Descend into that child and continue with the next letter.
            node = node.children[i]

        # We've placed every letter; mark this node as the end of a real word.
        node.end = True

    # Follow the same path the letters describe.

        # A missing branch means the word was never inserted.

    # The path exists — but it's only a match if a word actually ended here
    # (otherwise "app" would wrongly match when only "apple" was inserted).
# Each node has one child slot per lowercase letter, plus a flag marking
# whether a complete word ends here. Shared prefixes share the same path.
class Trie:
    def __init__(self):
        self.children = [None] * 26
        self.end = False
    def insert(self, word):
        # Start at the root and walk down one letter at a time.
        node = self
        for ch in word:
            # Map the letter to a slot 0..25.
            i = ord(ch) - ord('a')

            # If this letter has never been seen from here, grow a new branch.
            if node.children[i] is None:
                node.children[i] = Trie()

            # Descend into that child and continue with the next letter.
            node = node.children[i]

        # We've placed every letter; mark this node as the end of a real word.
        node.end = True
    def search(self, word):
        # Follow the same path the letters describe.
        node = self
        for ch in word:
            i = ord(ch) - ord('a')

            # A missing branch means the word was never inserted.
            if node.children[i] is None:
                return False
            node = node.children[i]

        # The path exists — but it's only a match if a word actually ended here
        # (otherwise "app" would wrongly match when only "apple" was inserted).
        return node.end
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
  constructor() {
    this.children = new Array(26).fill(null);
    this.end = false;
  }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
  constructor() {
    this.children = new Array(26).fill(null);
    this.end = false;
  }

  // Start at the root and walk down one letter at a time.
    // Map the letter to a slot 0..25.
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
  constructor() {
    this.children = new Array(26).fill(null);
    this.end = false;
  }

  insert(word) {
    // Start at the root and walk down one letter at a time.
    let node = this;
    for (const ch of word) {
      // Map the letter to a slot 0..25.
      const i = ch.charCodeAt(0) - 97;
    }
  }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
  constructor() {
    this.children = new Array(26).fill(null);
    this.end = false;
  }

  insert(word) {
    // Start at the root and walk down one letter at a time.
    let node = this;
    for (const ch of word) {
      // Map the letter to a slot 0..25.
      const i = ch.charCodeAt(0) - 97;

      // If this letter has never been seen from here, grow a new branch.

      // Descend into that child and continue with the next letter.
    }
  }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
  constructor() {
    this.children = new Array(26).fill(null);
    this.end = false;
  }

  insert(word) {
    // Start at the root and walk down one letter at a time.
    let node = this;
    for (const ch of word) {
      // Map the letter to a slot 0..25.
      const i = ch.charCodeAt(0) - 97;

      // If this letter has never been seen from here, grow a new branch.
      if (node.children[i] === null) {
        node.children[i] = new Trie();
      }

      // Descend into that child and continue with the next letter.
      node = node.children[i];
    }
  }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
  constructor() {
    this.children = new Array(26).fill(null);
    this.end = false;
  }

  insert(word) {
    // Start at the root and walk down one letter at a time.
    let node = this;
    for (const ch of word) {
      // Map the letter to a slot 0..25.
      const i = ch.charCodeAt(0) - 97;

      // If this letter has never been seen from here, grow a new branch.
      if (node.children[i] === null) {
        node.children[i] = new Trie();
      }

      // Descend into that child and continue with the next letter.
      node = node.children[i];
    }

  // We've placed every letter; mark this node as the end of a real word.
  }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
  constructor() {
    this.children = new Array(26).fill(null);
    this.end = false;
  }

  insert(word) {
    // Start at the root and walk down one letter at a time.
    let node = this;
    for (const ch of word) {
      // Map the letter to a slot 0..25.
      const i = ch.charCodeAt(0) - 97;

      // If this letter has never been seen from here, grow a new branch.
      if (node.children[i] === null) {
        node.children[i] = new Trie();
      }

      // Descend into that child and continue with the next letter.
      node = node.children[i];
    }

  // We've placed every letter; mark this node as the end of a real word.
    node.end = true;
  }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
  constructor() {
    this.children = new Array(26).fill(null);
    this.end = false;
  }

  insert(word) {
    // Start at the root and walk down one letter at a time.
    let node = this;
    for (const ch of word) {
      // Map the letter to a slot 0..25.
      const i = ch.charCodeAt(0) - 97;

      // If this letter has never been seen from here, grow a new branch.
      if (node.children[i] === null) {
        node.children[i] = new Trie();
      }

      // Descend into that child and continue with the next letter.
      node = node.children[i];
    }

  // We've placed every letter; mark this node as the end of a real word.
    node.end = true;
  }

  // Follow the same path the letters describe.

    // A missing branch means the word was never inserted.

  // The path exists — but it's only a match if a word actually ended here
  // (otherwise "app" would wrongly match when only "apple" was inserted).
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
  constructor() {
    this.children = new Array(26).fill(null);
    this.end = false;
  }

  insert(word) {
    // Start at the root and walk down one letter at a time.
    let node = this;
    for (const ch of word) {
      // Map the letter to a slot 0..25.
      const i = ch.charCodeAt(0) - 97;

      // If this letter has never been seen from here, grow a new branch.
      if (node.children[i] === null) {
        node.children[i] = new Trie();
      }

      // Descend into that child and continue with the next letter.
      node = node.children[i];
    }

  // We've placed every letter; mark this node as the end of a real word.
    node.end = true;
  }

  search(word) {
    // Follow the same path the letters describe.
    let node = this;
    for (const ch of word) {
      const i = ch.charCodeAt(0) - 97;

      // A missing branch means the word was never inserted.
      if (node.children[i] === null) {
        return false;
      }
      node = node.children[i];
    }

    // The path exists — but it's only a match if a word actually ended here
    // (otherwise "app" would wrongly match when only "apple" was inserted).
    return node.end;
  }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
  private children: (Trie | null)[];
  private end: boolean;

  constructor() {
    this.children = new Array(26).fill(null);
    this.end = false;
  }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
  private children: (Trie | null)[];
  private end: boolean;

  constructor() {
    this.children = new Array(26).fill(null);
    this.end = false;
  }

  // Start at the root and walk down one letter at a time.
    // Map the letter to a slot 0..25.
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
  private children: (Trie | null)[];
  private end: boolean;

  constructor() {
    this.children = new Array(26).fill(null);
    this.end = false;
  }

  insert(word: string): void {
    // Start at the root and walk down one letter at a time.
    let node: Trie = this;
    for (const ch of word) {
      // Map the letter to a slot 0..25.
      const i = ch.charCodeAt(0) - 97;
    }
  }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
  private children: (Trie | null)[];
  private end: boolean;

  constructor() {
    this.children = new Array(26).fill(null);
    this.end = false;
  }

  insert(word: string): void {
    // Start at the root and walk down one letter at a time.
    let node: Trie = this;
    for (const ch of word) {
      // Map the letter to a slot 0..25.
      const i = ch.charCodeAt(0) - 97;

      // If this letter has never been seen from here, grow a new branch.

      // Descend into that child and continue with the next letter.
    }
  }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
  private children: (Trie | null)[];
  private end: boolean;

  constructor() {
    this.children = new Array(26).fill(null);
    this.end = false;
  }

  insert(word: string): void {
    // Start at the root and walk down one letter at a time.
    let node: Trie = this;
    for (const ch of word) {
      // Map the letter to a slot 0..25.
      const i = ch.charCodeAt(0) - 97;

      // If this letter has never been seen from here, grow a new branch.
      if (node.children[i] === null) {
        node.children[i] = new Trie();
      }

      // Descend into that child and continue with the next letter.
      node = node.children[i] as Trie;
    }
  }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
  private children: (Trie | null)[];
  private end: boolean;

  constructor() {
    this.children = new Array(26).fill(null);
    this.end = false;
  }

  insert(word: string): void {
    // Start at the root and walk down one letter at a time.
    let node: Trie = this;
    for (const ch of word) {
      // Map the letter to a slot 0..25.
      const i = ch.charCodeAt(0) - 97;

      // If this letter has never been seen from here, grow a new branch.
      if (node.children[i] === null) {
        node.children[i] = new Trie();
      }

      // Descend into that child and continue with the next letter.
      node = node.children[i] as Trie;
    }

  // We've placed every letter; mark this node as the end of a real word.
  }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
  private children: (Trie | null)[];
  private end: boolean;

  constructor() {
    this.children = new Array(26).fill(null);
    this.end = false;
  }

  insert(word: string): void {
    // Start at the root and walk down one letter at a time.
    let node: Trie = this;
    for (const ch of word) {
      // Map the letter to a slot 0..25.
      const i = ch.charCodeAt(0) - 97;

      // If this letter has never been seen from here, grow a new branch.
      if (node.children[i] === null) {
        node.children[i] = new Trie();
      }

      // Descend into that child and continue with the next letter.
      node = node.children[i] as Trie;
    }

  // We've placed every letter; mark this node as the end of a real word.
    node.end = true;
  }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
  private children: (Trie | null)[];
  private end: boolean;

  constructor() {
    this.children = new Array(26).fill(null);
    this.end = false;
  }

  insert(word: string): void {
    // Start at the root and walk down one letter at a time.
    let node: Trie = this;
    for (const ch of word) {
      // Map the letter to a slot 0..25.
      const i = ch.charCodeAt(0) - 97;

      // If this letter has never been seen from here, grow a new branch.
      if (node.children[i] === null) {
        node.children[i] = new Trie();
      }

      // Descend into that child and continue with the next letter.
      node = node.children[i] as Trie;
    }

  // We've placed every letter; mark this node as the end of a real word.
    node.end = true;
  }

  // Follow the same path the letters describe.

    // A missing branch means the word was never inserted.

  // The path exists — but it's only a match if a word actually ended here
  // (otherwise "app" would wrongly match when only "apple" was inserted).
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
  private children: (Trie | null)[];
  private end: boolean;

  constructor() {
    this.children = new Array(26).fill(null);
    this.end = false;
  }

  insert(word: string): void {
    // Start at the root and walk down one letter at a time.
    let node: Trie = this;
    for (const ch of word) {
      // Map the letter to a slot 0..25.
      const i = ch.charCodeAt(0) - 97;

      // If this letter has never been seen from here, grow a new branch.
      if (node.children[i] === null) {
        node.children[i] = new Trie();
      }

      // Descend into that child and continue with the next letter.
      node = node.children[i] as Trie;
    }

  // We've placed every letter; mark this node as the end of a real word.
    node.end = true;
  }

  search(word: string): boolean {
    // Follow the same path the letters describe.
    let node: Trie = this;
    for (const ch of word) {
      const i = ch.charCodeAt(0) - 97;

      // A missing branch means the word was never inserted.
      if (node.children[i] === null) {
        return false;
      }
      node = node.children[i] as Trie;
    }

    // The path exists — but it's only a match if a word actually ended here
    // (otherwise "app" would wrongly match when only "apple" was inserted).
    return node.end;
  }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
    private final Trie[] children = new Trie[26];
    private boolean end = false;
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
    private final Trie[] children = new Trie[26];
    private boolean end = false;

    // Start at the root and walk down one letter at a time.
        // Map the letter to a slot 0..25.
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
    private final Trie[] children = new Trie[26];
    private boolean end = false;

    void insert(String word) {
        // Start at the root and walk down one letter at a time.
        Trie node = this;
        for (char ch : word.toCharArray()) {
            // Map the letter to a slot 0..25.
            int i = ch - 'a';
        }
    }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
    private final Trie[] children = new Trie[26];
    private boolean end = false;

    void insert(String word) {
        // Start at the root and walk down one letter at a time.
        Trie node = this;
        for (char ch : word.toCharArray()) {
            // Map the letter to a slot 0..25.
            int i = ch - 'a';

            // If this letter has never been seen from here, grow a new branch.

            // Descend into that child and continue with the next letter.
        }
    }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
    private final Trie[] children = new Trie[26];
    private boolean end = false;

    void insert(String word) {
        // Start at the root and walk down one letter at a time.
        Trie node = this;
        for (char ch : word.toCharArray()) {
            // Map the letter to a slot 0..25.
            int i = ch - 'a';

            // If this letter has never been seen from here, grow a new branch.
            if (node.children[i] == null) {
                node.children[i] = new Trie();
            }

            // Descend into that child and continue with the next letter.
            node = node.children[i];
        }
    }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
    private final Trie[] children = new Trie[26];
    private boolean end = false;

    void insert(String word) {
        // Start at the root and walk down one letter at a time.
        Trie node = this;
        for (char ch : word.toCharArray()) {
            // Map the letter to a slot 0..25.
            int i = ch - 'a';

            // If this letter has never been seen from here, grow a new branch.
            if (node.children[i] == null) {
                node.children[i] = new Trie();
            }

            // Descend into that child and continue with the next letter.
            node = node.children[i];
        }

    // We've placed every letter; mark this node as the end of a real word.
    }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
    private final Trie[] children = new Trie[26];
    private boolean end = false;

    void insert(String word) {
        // Start at the root and walk down one letter at a time.
        Trie node = this;
        for (char ch : word.toCharArray()) {
            // Map the letter to a slot 0..25.
            int i = ch - 'a';

            // If this letter has never been seen from here, grow a new branch.
            if (node.children[i] == null) {
                node.children[i] = new Trie();
            }

            // Descend into that child and continue with the next letter.
            node = node.children[i];
        }

    // We've placed every letter; mark this node as the end of a real word.
        node.end = true;
    }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
    private final Trie[] children = new Trie[26];
    private boolean end = false;

    void insert(String word) {
        // Start at the root and walk down one letter at a time.
        Trie node = this;
        for (char ch : word.toCharArray()) {
            // Map the letter to a slot 0..25.
            int i = ch - 'a';

            // If this letter has never been seen from here, grow a new branch.
            if (node.children[i] == null) {
                node.children[i] = new Trie();
            }

            // Descend into that child and continue with the next letter.
            node = node.children[i];
        }

    // We've placed every letter; mark this node as the end of a real word.
        node.end = true;
    }

    // Follow the same path the letters describe.

        // A missing branch means the word was never inserted.

    // The path exists — but it's only a match if a word actually ended here
    // (otherwise "app" would wrongly match when only "apple" was inserted).
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
    private final Trie[] children = new Trie[26];
    private boolean end = false;

    void insert(String word) {
        // Start at the root and walk down one letter at a time.
        Trie node = this;
        for (char ch : word.toCharArray()) {
            // Map the letter to a slot 0..25.
            int i = ch - 'a';

            // If this letter has never been seen from here, grow a new branch.
            if (node.children[i] == null) {
                node.children[i] = new Trie();
            }

            // Descend into that child and continue with the next letter.
            node = node.children[i];
        }

    // We've placed every letter; mark this node as the end of a real word.
        node.end = true;
    }

    boolean search(String word) {
        // Follow the same path the letters describe.
        Trie node = this;
        for (char ch : word.toCharArray()) {
            int i = ch - 'a';

            // A missing branch means the word was never inserted.
            if (node.children[i] == null) {
                return false;
            }
            node = node.children[i];
        }

        // The path exists — but it's only a match if a word actually ended here
        // (otherwise "app" would wrongly match when only "apple" was inserted).
        return node.end;
    }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
public class Trie {
    private readonly Trie[] children = new Trie[26];
    private bool end = false;
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
public class Trie {
    private readonly Trie[] children = new Trie[26];
    private bool end = false;

    // Start at the root and walk down one letter at a time.
        // Map the letter to a slot 0..25.
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
public class Trie {
    private readonly Trie[] children = new Trie[26];
    private bool end = false;

    public void Insert(string word) {
        // Start at the root and walk down one letter at a time.
        Trie node = this;
        foreach (char ch in word) {
            // Map the letter to a slot 0..25.
            int i = ch - 'a';
        }
    }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
public class Trie {
    private readonly Trie[] children = new Trie[26];
    private bool end = false;

    public void Insert(string word) {
        // Start at the root and walk down one letter at a time.
        Trie node = this;
        foreach (char ch in word) {
            // Map the letter to a slot 0..25.
            int i = ch - 'a';

            // If this letter has never been seen from here, grow a new branch.

            // Descend into that child and continue with the next letter.
        }
    }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
public class Trie {
    private readonly Trie[] children = new Trie[26];
    private bool end = false;

    public void Insert(string word) {
        // Start at the root and walk down one letter at a time.
        Trie node = this;
        foreach (char ch in word) {
            // Map the letter to a slot 0..25.
            int i = ch - 'a';

            // If this letter has never been seen from here, grow a new branch.
            if (node.children[i] == null) {
                node.children[i] = new Trie();
            }

            // Descend into that child and continue with the next letter.
            node = node.children[i];
        }
    }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
public class Trie {
    private readonly Trie[] children = new Trie[26];
    private bool end = false;

    public void Insert(string word) {
        // Start at the root and walk down one letter at a time.
        Trie node = this;
        foreach (char ch in word) {
            // Map the letter to a slot 0..25.
            int i = ch - 'a';

            // If this letter has never been seen from here, grow a new branch.
            if (node.children[i] == null) {
                node.children[i] = new Trie();
            }

            // Descend into that child and continue with the next letter.
            node = node.children[i];
        }

    // We've placed every letter; mark this node as the end of a real word.
    }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
public class Trie {
    private readonly Trie[] children = new Trie[26];
    private bool end = false;

    public void Insert(string word) {
        // Start at the root and walk down one letter at a time.
        Trie node = this;
        foreach (char ch in word) {
            // Map the letter to a slot 0..25.
            int i = ch - 'a';

            // If this letter has never been seen from here, grow a new branch.
            if (node.children[i] == null) {
                node.children[i] = new Trie();
            }

            // Descend into that child and continue with the next letter.
            node = node.children[i];
        }

    // We've placed every letter; mark this node as the end of a real word.
        node.end = true;
    }
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
public class Trie {
    private readonly Trie[] children = new Trie[26];
    private bool end = false;

    public void Insert(string word) {
        // Start at the root and walk down one letter at a time.
        Trie node = this;
        foreach (char ch in word) {
            // Map the letter to a slot 0..25.
            int i = ch - 'a';

            // If this letter has never been seen from here, grow a new branch.
            if (node.children[i] == null) {
                node.children[i] = new Trie();
            }

            // Descend into that child and continue with the next letter.
            node = node.children[i];
        }

    // We've placed every letter; mark this node as the end of a real word.
        node.end = true;
    }

    // Follow the same path the letters describe.

        // A missing branch means the word was never inserted.

    // The path exists — but it's only a match if a word actually ended here
    // (otherwise "app" would wrongly match when only "apple" was inserted).
}
// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
public class Trie {
    private readonly Trie[] children = new Trie[26];
    private bool end = false;

    public void Insert(string word) {
        // Start at the root and walk down one letter at a time.
        Trie node = this;
        foreach (char ch in word) {
            // Map the letter to a slot 0..25.
            int i = ch - 'a';

            // If this letter has never been seen from here, grow a new branch.
            if (node.children[i] == null) {
                node.children[i] = new Trie();
            }

            // Descend into that child and continue with the next letter.
            node = node.children[i];
        }

    // We've placed every letter; mark this node as the end of a real word.
        node.end = true;
    }

    public bool Search(string word) {
        // Follow the same path the letters describe.
        Trie node = this;
        foreach (char ch in word) {
            int i = ch - 'a';

            // A missing branch means the word was never inserted.
            if (node.children[i] == null) {
                return false;
            }
            node = node.children[i];
        }

        // The path exists — but it's only a match if a word actually ended here
        // (otherwise "app" would wrongly match when only "apple" was inserted).
        return node.end;
    }
}
#include <stdbool.h>
#include <stdlib.h>

// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
typedef struct Trie {
    struct Trie* children[26];
    bool end;
} Trie;
#include <stdbool.h>
#include <stdlib.h>

// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
typedef struct Trie {
    struct Trie* children[26];
    bool end;
} Trie;

// Start at the root and walk down one letter at a time.
        // Map the letter to a slot 0..25.
#include <stdbool.h>
#include <stdlib.h>

// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
typedef struct Trie {
    struct Trie* children[26];
    bool end;
} Trie;

void trieInsert(Trie* root, const char* word) {
    // Start at the root and walk down one letter at a time.
    Trie* node = root;
    for (const char* p = word; *p; p++) {
        // Map the letter to a slot 0..25.
        int i = *p - 'a';
    }
}
#include <stdbool.h>
#include <stdlib.h>

// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
typedef struct Trie {
    struct Trie* children[26];
    bool end;
} Trie;

void trieInsert(Trie* root, const char* word) {
    // Start at the root and walk down one letter at a time.
    Trie* node = root;
    for (const char* p = word; *p; p++) {
        // Map the letter to a slot 0..25.
        int i = *p - 'a';

        // If this letter has never been seen from here, grow a new branch.

        // Descend into that child and continue with the next letter.
    }
}
#include <stdbool.h>
#include <stdlib.h>

// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
typedef struct Trie {
    struct Trie* children[26];
    bool end;
} Trie;

void trieInsert(Trie* root, const char* word) {
    // Start at the root and walk down one letter at a time.
    Trie* node = root;
    for (const char* p = word; *p; p++) {
        // Map the letter to a slot 0..25.
        int i = *p - 'a';

        // If this letter has never been seen from here, grow a new branch.
        if (node->children[i] == NULL) {
            node->children[i] = calloc(1, sizeof(Trie));
        }

        // Descend into that child and continue with the next letter.
        node = node->children[i];
    }
}
#include <stdbool.h>
#include <stdlib.h>

// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
typedef struct Trie {
    struct Trie* children[26];
    bool end;
} Trie;

void trieInsert(Trie* root, const char* word) {
    // Start at the root and walk down one letter at a time.
    Trie* node = root;
    for (const char* p = word; *p; p++) {
        // Map the letter to a slot 0..25.
        int i = *p - 'a';

        // If this letter has never been seen from here, grow a new branch.
        if (node->children[i] == NULL) {
            node->children[i] = calloc(1, sizeof(Trie));
        }

        // Descend into that child and continue with the next letter.
        node = node->children[i];
    }

    // We've placed every letter; mark this node as the end of a real word.
}
#include <stdbool.h>
#include <stdlib.h>

// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
typedef struct Trie {
    struct Trie* children[26];
    bool end;
} Trie;

void trieInsert(Trie* root, const char* word) {
    // Start at the root and walk down one letter at a time.
    Trie* node = root;
    for (const char* p = word; *p; p++) {
        // Map the letter to a slot 0..25.
        int i = *p - 'a';

        // If this letter has never been seen from here, grow a new branch.
        if (node->children[i] == NULL) {
            node->children[i] = calloc(1, sizeof(Trie));
        }

        // Descend into that child and continue with the next letter.
        node = node->children[i];
    }

    // We've placed every letter; mark this node as the end of a real word.
    node->end = true;
}
#include <stdbool.h>
#include <stdlib.h>

// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
typedef struct Trie {
    struct Trie* children[26];
    bool end;
} Trie;

void trieInsert(Trie* root, const char* word) {
    // Start at the root and walk down one letter at a time.
    Trie* node = root;
    for (const char* p = word; *p; p++) {
        // Map the letter to a slot 0..25.
        int i = *p - 'a';

        // If this letter has never been seen from here, grow a new branch.
        if (node->children[i] == NULL) {
            node->children[i] = calloc(1, sizeof(Trie));
        }

        // Descend into that child and continue with the next letter.
        node = node->children[i];
    }

    // We've placed every letter; mark this node as the end of a real word.
    node->end = true;
}

// Follow the same path the letters describe.

    // A missing branch means the word was never inserted.

// The path exists — but it's only a match if a word actually ended here
// (otherwise "app" would wrongly match when only "apple" was inserted).
#include <stdbool.h>
#include <stdlib.h>

// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
typedef struct Trie {
    struct Trie* children[26];
    bool end;
} Trie;

void trieInsert(Trie* root, const char* word) {
    // Start at the root and walk down one letter at a time.
    Trie* node = root;
    for (const char* p = word; *p; p++) {
        // Map the letter to a slot 0..25.
        int i = *p - 'a';

        // If this letter has never been seen from here, grow a new branch.
        if (node->children[i] == NULL) {
            node->children[i] = calloc(1, sizeof(Trie));
        }

        // Descend into that child and continue with the next letter.
        node = node->children[i];
    }

    // We've placed every letter; mark this node as the end of a real word.
    node->end = true;
}

bool trieSearch(Trie* root, const char* word) {
    // Follow the same path the letters describe.
    Trie* node = root;
    for (const char* p = word; *p; p++) {
        int i = *p - 'a';

        // A missing branch means the word was never inserted.
        if (node->children[i] == NULL) {
            return false;
        }
        node = node->children[i];
    }

    // The path exists — but it's only a match if a word actually ended here
    // (otherwise "app" would wrongly match when only "apple" was inserted).
    return node->end;
}
#include <string>
using namespace std;

// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
    Trie* children[26] = {};
    bool end = false;

public:
};
#include <string>
using namespace std;

// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
    Trie* children[26] = {};
    bool end = false;

public:

    // Start at the root and walk down one letter at a time.
        // Map the letter to a slot 0..25.
};
#include <string>
using namespace std;

// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
    Trie* children[26] = {};
    bool end = false;

public:
    void insert(const string& word) {
        // Start at the root and walk down one letter at a time.
        Trie* node = this;
        for (char ch : word) {
            // Map the letter to a slot 0..25.
            int i = ch - 'a';
        }
    }
};
#include <string>
using namespace std;

// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
    Trie* children[26] = {};
    bool end = false;

public:
    void insert(const string& word) {
        // Start at the root and walk down one letter at a time.
        Trie* node = this;
        for (char ch : word) {
            // Map the letter to a slot 0..25.
            int i = ch - 'a';

            // If this letter has never been seen from here, grow a new branch.

            // Descend into that child and continue with the next letter.
        }
    }
};
#include <string>
using namespace std;

// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
    Trie* children[26] = {};
    bool end = false;

public:
    void insert(const string& word) {
        // Start at the root and walk down one letter at a time.
        Trie* node = this;
        for (char ch : word) {
            // Map the letter to a slot 0..25.
            int i = ch - 'a';

            // If this letter has never been seen from here, grow a new branch.
            if (node->children[i] == nullptr) {
                node->children[i] = new Trie();
            }

            // Descend into that child and continue with the next letter.
            node = node->children[i];
        }
    }
};
#include <string>
using namespace std;

// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
    Trie* children[26] = {};
    bool end = false;

public:
    void insert(const string& word) {
        // Start at the root and walk down one letter at a time.
        Trie* node = this;
        for (char ch : word) {
            // Map the letter to a slot 0..25.
            int i = ch - 'a';

            // If this letter has never been seen from here, grow a new branch.
            if (node->children[i] == nullptr) {
                node->children[i] = new Trie();
            }

            // Descend into that child and continue with the next letter.
            node = node->children[i];
        }

    // We've placed every letter; mark this node as the end of a real word.
    }
};
#include <string>
using namespace std;

// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
    Trie* children[26] = {};
    bool end = false;

public:
    void insert(const string& word) {
        // Start at the root and walk down one letter at a time.
        Trie* node = this;
        for (char ch : word) {
            // Map the letter to a slot 0..25.
            int i = ch - 'a';

            // If this letter has never been seen from here, grow a new branch.
            if (node->children[i] == nullptr) {
                node->children[i] = new Trie();
            }

            // Descend into that child and continue with the next letter.
            node = node->children[i];
        }

    // We've placed every letter; mark this node as the end of a real word.
        node->end = true;
    }
};
#include <string>
using namespace std;

// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
    Trie* children[26] = {};
    bool end = false;

public:
    void insert(const string& word) {
        // Start at the root and walk down one letter at a time.
        Trie* node = this;
        for (char ch : word) {
            // Map the letter to a slot 0..25.
            int i = ch - 'a';

            // If this letter has never been seen from here, grow a new branch.
            if (node->children[i] == nullptr) {
                node->children[i] = new Trie();
            }

            // Descend into that child and continue with the next letter.
            node = node->children[i];
        }

    // We've placed every letter; mark this node as the end of a real word.
        node->end = true;
    }

    // Follow the same path the letters describe.

        // A missing branch means the word was never inserted.

    // The path exists — but it's only a match if a word actually ended here
    // (otherwise "app" would wrongly match when only "apple" was inserted).
};
#include <string>
using namespace std;

// Each node has one child slot per lowercase letter, plus a flag marking
// whether a complete word ends here. Shared prefixes share the same path.
class Trie {
    Trie* children[26] = {};
    bool end = false;

public:
    void insert(const string& word) {
        // Start at the root and walk down one letter at a time.
        Trie* node = this;
        for (char ch : word) {
            // Map the letter to a slot 0..25.
            int i = ch - 'a';

            // If this letter has never been seen from here, grow a new branch.
            if (node->children[i] == nullptr) {
                node->children[i] = new Trie();
            }

            // Descend into that child and continue with the next letter.
            node = node->children[i];
        }

    // We've placed every letter; mark this node as the end of a real word.
        node->end = true;
    }

    bool search(const string& word) {
        // Follow the same path the letters describe.
        Trie* node = this;
        for (char ch : word) {
            int i = ch - 'a';

            // A missing branch means the word was never inserted.
            if (node->children[i] == nullptr) {
                return false;
            }
            node = node->children[i];
        }

        // The path exists — but it's only a match if a word actually ended here
        // (otherwise "app" would wrongly match when only "apple" was inserted).
        return node->end;
    }
};

Tap the left half to go back, the right half to go forward.

Arrow keys or space to navigate · Esc to exit.