Advertisement
jules0707

TrieSET26.java

May 3rd, 2021 (edited)
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 9.69 KB | None | 0 0
  1. import edu.princeton.cs.algs4.Queue;
  2. import edu.princeton.cs.algs4.StdIn;
  3. import edu.princeton.cs.algs4.StdOut;
  4. import java.util.Iterator;
  5.  
  6. public class TrieSET26 implements Iterable<String> {
  7.     private static final int R = 26; // letters A through Z
  8.  
  9.     private Node root;      // root of trie
  10.     private int n;          // number of keys in trie
  11.  
  12.     // R-way trie node
  13.     private static class Node {
  14.         private Node[] next = new Node[R];
  15.         private boolean isString;
  16.     }
  17.  
  18.     /**
  19.      * Initializes an empty set of strings.
  20.      */
  21.     public TrieSET26() {
  22.     }
  23.  
  24.     /**
  25.      * Does the set contain the given key?
  26.      * @param key the key
  27.      * @return {@code true} if the set contains {@code key} and
  28.      *     {@code false} otherwise
  29.      * @throws IllegalArgumentException if {@code key} is {@code null}
  30.      */
  31.     public boolean contains(String key) {
  32.         if (key == null) throw new IllegalArgumentException("argument to contains() is null");
  33.         Node x = get(root, key, 0);
  34.         if (x == null) return false;
  35.         return x.isString;
  36.     }
  37.  
  38.     private Node get(Node x, String key, int d) {
  39.         if (x == null) return null;
  40.         if (d == key.length()) return x;
  41.         char c = key.charAt(d);
  42.         return get(x.next[c-65], key, d + 1); // first capital letter of alphabet A in '65' position in 256 ASCII array
  43.     }
  44.  
  45.     /**
  46.      * Adds the key to the set if it is not already present.
  47.      * @param key the key to add
  48.      * @throws IllegalArgumentException if {@code key} is {@code null}
  49.      */
  50.     public void add(String key) {
  51.         if (key == null) throw new IllegalArgumentException("argument to add() is null");
  52.         root = add(root, key, 0);
  53.     }
  54.  
  55.     private Node add(Node x, String key, int d) {
  56.         if (x == null) x = new Node();
  57.         if (d == key.length()) {
  58.             if (!x.isString) n++;
  59.             x.isString = true;
  60.         } else {
  61.             char c = key.charAt(d);
  62.             x.next[c-65] = add(x.next[c-65], key, d + 1); // convert a 256-way ASCII trie to 26-way A-Z trie
  63.         }
  64.         return x;
  65.     }
  66.  
  67.     /**
  68.      * Returns the number of strings in the set.
  69.      * @return the number of strings in the set
  70.      */
  71.     public int size() {
  72.         return n;
  73.     }
  74.  
  75.     /**
  76.      * Is the set empty?
  77.      * @return {@code true} if the set is empty, and {@code false} otherwise
  78.      */
  79.     public boolean isEmpty() {
  80.         return size() == 0;
  81.     }
  82.  
  83.     /**
  84.      * Returns all of the keys in the set, as an iterator.
  85.      * To iterate over all of the keys in a set named {@code set}, use the
  86.      * foreach notation: {@code for (Key key : set)}.
  87.      * @return an iterator to all of the keys in the set
  88.      */
  89.     public Iterator<String> iterator() {
  90.         return keysWithPrefix("").iterator();
  91.     }
  92.  
  93.  
  94.     public boolean hasKeysWithPrefix(String key){
  95.         Node x = get(root,key, 0);
  96.         return x != null;
  97.     }
  98.  
  99.     /**
  100.      * Returns all of the keys in the set that start with {@code prefix}.
  101.      * @param prefix the prefix
  102.      * @return all of the keys in the set that start with {@code prefix},
  103.      *     as an iterable
  104.      */
  105.     public Iterable<String> keysWithPrefix(String prefix) {
  106.         Queue<String> results = new Queue<String>();
  107.         Node x = get(root, prefix, 0);
  108.         collect(x, new StringBuilder(prefix), results);
  109.         return results;
  110.     }
  111.  
  112.     private void collect(Node x, StringBuilder prefix, Queue<String> results) {
  113.         if (x == null) return;
  114.         if (x.isString) results.enqueue(prefix.toString());
  115.         for (char c = 0; c < R; c++) {
  116.             prefix.append(c);
  117.             collect(x.next[c], prefix, results);
  118.             prefix.deleteCharAt(prefix.length() - 1);
  119.         }
  120.     }
  121.  
  122.     /**
  123.      * Returns all of the keys in the set that match {@code pattern},
  124.      * where . symbol is treated as a wildcard character.
  125.      * @param pattern the pattern
  126.      * @return all of the keys in the set that match {@code pattern},
  127.      *     as an iterable, where . is treated as a wildcard character.
  128.      */
  129.     public Iterable<String> keysThatMatch(String pattern) {
  130.         Queue<String> results = new Queue<String>();
  131.         StringBuilder prefix = new StringBuilder();
  132.         collect(root, prefix, pattern, results);
  133.         return results;
  134.     }
  135.  
  136.     private void collect(Node x, StringBuilder prefix, String pattern, Queue<String> results) {
  137.         if (x == null) return;
  138.         int d = prefix.length();
  139.         if (d == pattern.length() && x.isString)
  140.             results.enqueue(prefix.toString());
  141.         if (d == pattern.length())
  142.             return;
  143.         char c = pattern.charAt(d);
  144.         if (c == '.') {
  145.             for (char ch = 0; ch < R; ch++) {
  146.                 prefix.append(ch);
  147.                 collect(x.next[ch], prefix, pattern, results);
  148.                 prefix.deleteCharAt(prefix.length() - 1);
  149.             }
  150.         } else {
  151.             prefix.append(c);
  152.             collect(x.next[c], prefix, pattern, results);
  153.             prefix.deleteCharAt(prefix.length() - 1);
  154.         }
  155.     }
  156.  
  157.     /**
  158.      * Returns the string in the set that is the longest prefix of {@code query},
  159.      * or {@code null}, if no such string.
  160.      * @param query the query string
  161.      * @return the string in the set that is the longest prefix of {@code query},
  162.      *     or {@code null} if no such string
  163.      * @throws IllegalArgumentException if {@code query} is {@code null}
  164.      */
  165.     public String longestPrefixOf(String query) {
  166.         if (query == null) throw new IllegalArgumentException("argument to longestPrefixOf() is null");
  167.         int length = longestPrefixOf(root, query, 0, -1);
  168.         if (length == -1) return null;
  169.         return query.substring(0, length);
  170.     }
  171.  
  172.     // returns the length of the longest string key in the subtrie
  173.     // rooted at x that is a prefix of the query string,
  174.     // assuming the first d character match and we have already
  175.     // found a prefix match of length length
  176.     private int longestPrefixOf(Node x, String query, int d, int length) {
  177.         if (x == null) return length;
  178.         if (x.isString) length = d;
  179.         if (d == query.length()) return length;
  180.         char c = query.charAt(d);
  181.         return longestPrefixOf(x.next[c], query, d + 1, length);
  182.     }
  183.  
  184.     /**
  185.      * Removes the key from the set if the key is present.
  186.      * @param key the key
  187.      * @throws IllegalArgumentException if {@code key} is {@code null}
  188.      */
  189.     public void delete(String key) {
  190.         if (key == null) throw new IllegalArgumentException("argument to delete() is null");
  191.         root = delete(root, key, 0);
  192.     }
  193.  
  194.     private Node delete(Node x, String key, int d) {
  195.         if (x == null) return null;
  196.         if (d == key.length()) {
  197.             if (x.isString) n--;
  198.             x.isString = false;
  199.         } else {
  200.             char c = key.charAt(d);
  201.             x.next[c] = delete(x.next[c], key, d + 1);
  202.         }
  203.  
  204.         // remove subtrie rooted at x if it is completely empty
  205.         if (x.isString) return x;
  206.         for (int c = 0; c < R; c++)
  207.             if (x.next[c] != null)
  208.                 return x;
  209.         return null;
  210.     }
  211.  
  212.  
  213.     /**
  214.      * Unit tests the {@code TrieSET} data type.
  215.      *
  216.      * @param args the command-line arguments
  217.      */
  218.     public static void main(String[] args) {
  219.         edu.princeton.cs.algs4.TrieSET set = new edu.princeton.cs.algs4.TrieSET();
  220.         while (!StdIn.isEmpty()) {
  221.             String key = StdIn.readString();
  222.             set.add(key);
  223.         }
  224.  
  225.         // print results
  226.         if (set.size() < 100) {
  227.             StdOut.println("keys(\"\"):");
  228.             for (String key : set) {
  229.                 StdOut.println(key);
  230.             }
  231.             StdOut.println();
  232.         }
  233.  
  234.         StdOut.println("longestPrefixOf(\"shellsort\"):");
  235.         StdOut.println(set.longestPrefixOf("shellsort"));
  236.         StdOut.println();
  237.  
  238.         StdOut.println("longestPrefixOf(\"xshellsort\"):");
  239.         StdOut.println(set.longestPrefixOf("xshellsort"));
  240.         StdOut.println();
  241.  
  242.         StdOut.println("keysWithPrefix(\"shor\"):");
  243.         for (String s : set.keysWithPrefix("shor"))
  244.             StdOut.println(s);
  245.         StdOut.println();
  246.  
  247.         StdOut.println("keysWithPrefix(\"shortening\"):");
  248.         for (String s : set.keysWithPrefix("shortening"))
  249.             StdOut.println(s);
  250.         StdOut.println();
  251.  
  252.         StdOut.println("keysThatMatch(\".he.l.\"):");
  253.         for (String s : set.keysThatMatch(".he.l."))
  254.             StdOut.println(s);
  255.     }
  256. }
  257.  
  258. /******************************************************************************
  259.  *  Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
  260.  *
  261.  *  This file is part of algs4.jar, which accompanies the textbook
  262.  *
  263.  *      Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
  264.  *      Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
  265.  *      http://algs4.cs.princeton.edu
  266.  *
  267.  *
  268.  *  algs4.jar is free software: you can redistribute it and/or modify
  269.  *  it under the terms of the GNU General Public License as published by
  270.  *  the Free Software Foundation, either version 3 of the License, or
  271.  *  (at your option) any later version.
  272.  *
  273.  *  algs4.jar is distributed in the hope that it will be useful,
  274.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  275.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  276.  *  GNU General Public License for more details.
  277.  *
  278.  *  You should have received a copy of the GNU General Public License
  279.  *  along with algs4.jar.  If not, see http://www.gnu.org/licenses.
  280.  ******************************************************************************/
  281.  
  282.  
  283.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement