package com.interview.suffixprefix; import java.util.HashMap; import java.util.Map; /** * Date 04/25/2016 * @author Tushar Roy * * Insert/delete/search into trie data structure * * Reference * https://en.wikipedia.org/wiki/Trie */ public class Trie { private class TrieNode { Map<Character, TrieNode> children; boolean endOfWord; public TrieNode() { children = new HashMap<>(); endOfWord = false; } } private final TrieNode root; public Trie() { root = new TrieNode(); } /** * Iterative implementation of insert into trie */ public void insert(String word) { TrieNode current = root; for (int i = 0; i < word.length(); i++) { char ch = word.charAt(i); TrieNode node = current.children.get(ch); if (node == null) { node = new TrieNode(); current.children.put(ch, node); } current = node; } //mark the current nodes endOfWord as true current.endOfWord = true; } /** * Recursive implementation of insert into trie */ public void insertRecursive(String word) { insertRecursive(root, word, 0); } private void insertRecursive(TrieNode current, String word, int index) { if (index == word.length()) { //if end of word is reached then mark endOfWord as true on current node current.endOfWord = true; return; } char ch = word.charAt(index); TrieNode node = current.children.get(ch); //if node does not exists in map then create one and put it into map if (node == null) { node = new TrieNode(); current.children.put(ch, node); } insertRecursive(node, word, index + 1); } /** * Iterative implementation of search into trie. */ public boolean search(String word) { TrieNode current = root; for (int i = 0; i < word.length(); i++) { char ch = word.charAt(i); TrieNode node = current.children.get(ch); //if node does not exist for given char then return false if (node == null) { return false; } current = node; } //return true of current's endOfWord is true else return false. return current.endOfWord; } /** * Recursive implementation of search into trie. */ public boolean searchRecursive(String word) { return searchRecursive(root, word, 0); } private boolean searchRecursive(TrieNode current, String word, int index) { if (index == word.length()) { //return true of current's endOfWord is true else return false. return current.endOfWord; } char ch = word.charAt(index); TrieNode node = current.children.get(ch); //if node does not exist for given char then return false if (node == null) { return false; } return searchRecursive(node, word, index + 1); } /** * Delete word from trie. */ public void delete(String word) { delete(root, word, 0); } /** * Returns true if parent should delete the mapping */ private boolean delete(TrieNode current, String word, int index) { if (index == word.length()) { //when end of word is reached only delete if currrent.endOfWord is true. if (!current.endOfWord) { return false; } current.endOfWord = false; //if current has no other mapping then return true return current.children.size() == 0; } char ch = word.charAt(index); TrieNode node = current.children.get(ch); if (node == null) { return false; } boolean shouldDeleteCurrentNode = delete(node, word, index + 1); //if true is returned then delete the mapping of character and trienode reference from map. if (shouldDeleteCurrentNode) { current.children.remove(ch); //return true if no mappings are left in the map. return current.children.size() == 0; } return false; } }