Given an array of n distinct non-empty strings, you need to generate minimal possible abbreviations for every word following rules below.
- Begin with the first character and then the number of characters abbreviated, which followed by the last character.
- If there are any conflict, that is more than one words share the same abbreviation, a longer prefix is used instead of only the first character until making the map from word to abbreviation become unique. In other words, a final abbreviation cannot map to more than one original words.
- If the abbreviation doesn't make the word shorter, then keep it as original.
Example:
Input: ["like", "god", "internal", "me", "internet", "interval", "intension", "face", "intrusion"] Output: ["l2e","god","internal","me","i6t","interval","inte4n","f2e","intr4n"]
- Both n and the length of each word will not exceed 400.
- The length of each word is greater than 1.
- The words consist of lowercase English letters only.
- The return answers should be in the same order as the original array.
Solution:
We start from only abbreviating 1 character and put all results into an array.
Then we go through the array and put the duplicate strings to a set and only stores the index of the original string in the list.
For these strings, we need to abbreviate one more character and to the same check.
Code:
public class Solution { public List<String> wordsAbbreviation(List<String> dict) { int n = dict.size(); String[] res = new String[n]; int[] prefix = new int[n]; for (int i = 0; i < n; i++) { prefix[i] = 1; res[i] = convert(dict.get(i), 1); } for (int i = 0; i < n; i++) { while (true) { HashSet<Integer> set = new HashSet<>(); for (int j = i + 1; j < n; j++) { if (res[i].equals(res[j])) { set.add(j); } } if (set.isEmpty()) { break; } set.add(i); for (int k : set) { res[k] = convert(dict.get(k), ++prefix[k]); } } } return Arrays.asList(res); } public String convert(String str, int k) { if (k > str.length() - 2) { return str; } String res = str.substring(0, k) + (str.length() - k - 1) + str.charAt(str.length() - 1); return res.length() < str.length() ? res : str; } }