LeetCode 288 - Unique Word Abbreviation


LIKE CODING: LeetCode [288] Unique Word Abbreviation
http://www.cnblogs.com/easonliu/p/4852129.html
An abbreviation of a word follows the form <first letter><number><last letter>. Below are some examples of word abbreviations:
a) it                      --> it    (no abbreviation)

     1
b) d|o|g                   --> d1g

              1    1  1
     1---5----0----5--8
c) i|nternationalizatio|n  --> i18n

              1
     1---5----0
d) l|ocalizatio|n          --> l10n
Assume you have a dictionary and given a word, find whether its abbreviation is unique in the dictionary. A word's abbreviation is unique if no other word from the dictionary has the same abbreviation.
Example: 
Given dictionary = [ "deer", "door", "cake", "card" ]

isUnique("dear") -> false
isUnique("cart") -> true
isUnique("cane") -> false
isUnique("make") -> true

http://buttercola.blogspot.com/2015/10/leetcode-unique-word-abbreviation.html
The question is a little bit tricky. 
There are only 2 conditions we return true for isUnique("word")
1. The abbr does not appear in the dict. 
2. The abbr is in the dict && the word appears one and only once in the dict. 

The solution above presumes that the dict does not contains duplicates. However, the OJ updates its test case that 
Input:["a","a"],isUnique("a")
Output:[false]
Expected:[true]

So the new solution we need to use two dictionaries, one save the abbr format and the other saves the original dict. The value stores the frequencies of each word. 

So how to determine if a word is unique in the abbrivation? There are still two cases to consider: 
1. If the abbr of the input word does not appear in the abbr dict, return true;
2. If the abbr of the input word DOES appears in the abbr dict, we must make sure the input word is in the dictionary AND the its abbreviation format can only appear once in the abbr dict. 
  -- Now here comes to the corner case that the dict contains duplicates. In this case, both the dict and abbr dict will store "a", 2. So in this way, a does not appear only once! So the solution to handle this edge case is we must make sure the word freq in the dict and abbr dict is exactly the same. So we can make sure the word has no other duplicated abbrivations in the abbr dict. 
    private Set<String> uniqueDict; // no need to be global
    private Map<String, String> abbrDict;
 
    public ValidWordAbbr(String[] dictionary) {
        uniqueDict = new HashSet<>();
        abbrDict = new HashMap<>();
         
        for (String word : dictionary) {
            if (!uniqueDict.contains(word)) {
                String abbr = getAbbr(word);
                if (!abbrDict.containsKey(abbr)) {
                    abbrDict.put(abbr, word);
                } else {
                    abbrDict.put(abbr, "");
                }
                 
                uniqueDict.add(word);
            }
        }
    }
 
    public boolean isUnique(String word) {
        if (word == null || word.length() == 0) {
            return true;
        }
         
        String abbr = getAbbr(word);
        if (!abbrDict.containsKey(abbr) || abbrDict.get(abbr).equals(word)) {
            return true;
        } else {
            return false;
        }
    }
     
    private String getAbbr(String word) {
        if (word == null || word.length() < 3) {
            return word;
        }
         
        StringBuffer sb = new StringBuffer();
        sb.append(word.charAt(0));
        sb.append(word.length() - 2);
        sb.append(word.charAt(word.length() - 1));
         
        return sb.toString();
 
    }

When build the abbr -> world mapping, if there is, no need to store a list, just set it as empty string -> not null(npe).

public class ValidWordAbbr {
    private Map<String, String> map;
    public ValidWordAbbr(String[] dictionary) {
        this.map = new HashMap<>();
         
        for (String word : dictionary) {
            String abbr = toAbbr(word);
            if (map.containsKey(abbr)) {
                map.put(abbr, "");
            } else {
                map.put(abbr, word);
            }
        }
    }
    public boolean isUnique(String word) {
        String abbr = toAbbr(word);
        if (!map.containsKey(abbr) || map.get(abbr).equals(word)) {
            return true;
        } else {
            return false;
        }
    }
     
    private String toAbbr(String s) {
        if (s == null || s.length() <= 2) {
            return s;
        }
         
        int len = s.length() - 2;
         
        String result = s.charAt(0) + "" + len + s.charAt(s.length() - 1);
         
        return result;
    }
}
The solution above presumes that the dict does not contains duplicates. However, the OJ updates its test case that 
Input:["a","a"],isUnique("a")
Output:[false]
Expected:[true]
https://leetcode.com/discuss/71652/java-solution-with-hashmap-string-string-beats-submissions
map.put(key, ""); is nice!
HashMap<String, String> map; public ValidWordAbbr(String[] dictionary) { map = new HashMap<String, String>(); for(String str:dictionary){ String key = getKey(str); // If there is more than one string belong to the same key // then the key will be invalid, we set the value to "" if(map.containsKey(key) && !map.get(key).equals(str)) map.put(key, ""); else map.put(key, str); } }
public boolean isUnique(String word) { String key = getKey(word); return !map.containsKey(key)||map.get(key).equals(word); } private String getKey(String str){ if(str.length()<=2) return str; return str.charAt(0)+Integer.toString(str.length()-2)+str.charAt(str.length()-1); }
https://leetcode.com/discuss/61658/share-my-java-solution
I think we don't need to contain a set in HashMap, since if we got more than one value corresponds to this key, then this key is just a marker of duplicates. So my suggestion is to replace the value in HashMap by string.
For duplicates, the value would be some special strings like empty string or null. For others, the value is simply the word that produces this key
The idea is pretty straightforward, we use a map to track a set of words that have the same abbreviation. The word is unique when its abbreviation does not exist in the map or it's the only one in the set.
Map<String, Set<String>> map = new HashMap<>(); public ValidWordAbbr(String[] dictionary) { // build the hashmap // the key is the abbreviation // the value is a hash set of the words that have the same abbreviation for (int i = 0; i < dictionary.length; i++) { String a = abbr(dictionary[i]); Set<String> set = map.containsKey(a) ? map.get(a) : new HashSet<>(); set.add(dictionary[i]); map.put(a, set); } } public boolean isUnique(String word) { String a = abbr(word); // it's unique when the abbreviation does not exist in the map or // it's the only word in the set return !map.containsKey(a) || (map.get(a).contains(word) && map.get(a).size() == 1); } String abbr(String s) { if (s.length() < 3) return s; return s.substring(0, 1) + String.valueOf(s.length() - 2) + s.substring(s.length() - 1); }

http://blog.csdn.net/xudli/article/details/48860911
  1. public class ValidWordAbbr {  
  2.     Map<String, Set<String> > map = new HashMap<>();  
  3.   
  4.     public ValidWordAbbr(String[] dictionary) {  
  5.         for(int i=0; i<dictionary.length; i++) {  
  6.             String s = dictionary[i];  
  7.             if(s.length() > 2 ) {  
  8.                 s = s.charAt(0) + Integer.toString(s.length()-2) + s.charAt(s.length()-1);  
  9.             }  
  10.             if(map.containsKey(s) ) {  
  11.                 map.get(s).add(dictionary[i]);  
  12.             } else {  
  13.                 Set<String> set = new HashSet<String>();  
  14.                 set.add(dictionary[i]);  
  15.                 map.put(s, set);  
  16.             }  
  17.         }  
  18.     }  
  19.   
  20.     public boolean isUnique(String word) {  
  21.         //input check  
  22.         String s = word;  
  23.         if(s.length() > 2 ) {  
  24.             s = s.charAt(0) + Integer.toString(s.length()-2) + s.charAt(s.length()-1);  
  25.         }  
  26.         if(!map.containsKey(s)) return true;  
  27.         else return map.get(s).contains(word) && map.get(s).size()<=1;  
  28.           
  29.     }  
  30. }  

class ValidWordAbbr {
    unordered_map<string, vector<string>> abbs;
public:
    string getAbb(string s){
        int n = s.size();
        if(n<=2) return s;
        else return s.substr(0,1)+to_string(n-2)+s.substr(n-1,1);
    }
    ValidWordAbbr(vector<string> &dictionary) {
        for(auto w:dictionary){
            abbs[getAbb(w)].push_back(w);
        }
    }
    bool isUnique(string word) {
        string key = getAbb(word);
        return abbs.count(key)==0 || ((int)abbs[key].size()==1&&abbs[key][0]==word);
    }
};
 2 private:
 3     unordered_map<string, int> m_map;
 4     unordered_set<string> m_set;
 5 public:
 6     ValidWordAbbr(vector<string> &dictionary) {
 7         for (auto word : dictionary) {
 8             m_set.insert(word);
 9             if (word.length() == 2) ++m_map[word];
10             else ++m_map[word.front() + to_string(word.length() - 2) + word.back()];
11         }
12     }
13 
14     bool isUnique(string word) {
15         string key;
16         if (word.length() == 2) key = word;
17         else key = word.front() + to_string(word.length() - 2) + word.back();
18         if (m_set.find(word) == m_set.end()) return m_map[key] < 1;
19         else return m_map[key] < 2;
20     }
21 };
http://likemyblogger.blogspot.com/2015/10/leetcode-288-unique-word-abbreviation.html
class ValidWordAbbr {
    unordered_map<string, vector<string>> abbs;
public:
    string getAbb(string s){
        int n = s.size();
        if(n<=2) return s;
        else return s.substr(0,1)+to_string(n-2)+s.substr(n-1,1);
    }
    ValidWordAbbr(vector<string> &dictionary) {
        for(auto w:dictionary){
            abbs[getAbb(w)].push_back(w);
        }
    }
    bool isUnique(string word) {
        string key = getAbb(word);
        return abbs.count(key)==0 || ((int)abbs[key].size()==1&&abbs[key][0]==word);
    }
};


https://discuss.leetcode.com/topic/37254/let-me-explain-the-question-with-better-examples
The description (A word's abbreviation is unique if no other word from the dictionary has the same abbreviation) is clear however a bit twisting. It took me a few "Wrong Answer"s to finally understand what it's asking for.
We are trying to search for a word in a dictionary. If this word (also this word’s abbreviation) is not in the dictionary OR this word and only it’s abbreviation in the dictionary. We call a word’s abbreviation unique.
EX:
1) [“dog”]; isUnique(“dig”);   
//False, because “dig” has the same abbreviation with “dog" and “dog” is already in the dictionary. It’s not unique.
2) [“dog”, “dog"]; isUnique(“dog”);  
//True, because “dog” is the only word that has “d1g” abbreviation.
3) [“dog”, “dig”]; isUnique(“dog”);   
//False, because if we have more than one word match to the same abbreviation, this abbreviation will never be unique.

http://www.cnblogs.com/grandyang/p/5220589.html
    ValidWordAbbr(vector<string> &dictionary) {
        for (auto a : dictionary) {
            string k = a[0] + to_string(a.size() - 2) + a.back();
            m[k].insert(a);
        }
    }
    bool isUnique(string word) {
        string k = word[0] + to_string(word.size() - 2) + word.back();
        return m[k].count(word) == m[k].size();
    }
private:
    unordered_map<string, set<string>> m;


Follow up:
http://massivealgorithms.blogspot.com/2016/10/leetcode-411-minimum-unique-word.html

Read full article from LIKE CODING: LeetCode [288] Unique Word Abbreviation

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts