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"]
Note:
- 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.
這道題讓我們求單詞的縮寫形式,就是首尾字母加上中間字符的個數組成的新字符串,但是要求是不能有重復的縮寫字符串,而且說明如果縮寫字符串的長度並沒有減小的話就保留原來的字符串,比如 god,縮寫成 g1d 也沒啥用,所以仍是 god。博主剛開始在研究題目中給的例子的時候有些疑惑,雖然知道 internal 和 interval 的縮寫形式都是 i6l,會沖突,博主剛開始不明白的是,為什么不能一個是 i6l,一個是 in5l,這樣不就不沖突了么,而題目中的縮寫形式居然都是原字符串。后來才搞清楚題目原來是說只要有沖突的都不能用,而 internal 和 interval 是典型的死杠上的一對,i6l,in5l,int4l,inte3l,inter2l,統統沖突,而再往后的縮寫長度就和原字符串一樣了,所以二者就都保留了原樣。理解了題意就好辦了,由於每個單詞的縮寫形式中數字前面的字母個數不一定相同,所以用一個 pre 數組來記錄每個單詞縮寫形式開頭字母的長度,初始化都為1,然后先求出所有單詞 pre 為1的縮寫形式,再來進行沖突處理。遍歷每一個縮寫字符串,進行 while 循環,新建一個 HashSet,然后遍歷其他所有字符串,所有發現沖突字符串,就把沖突字符串的坐標存入 HashSet 中,如果沒有沖突,那么 HashSet 為空,直接 break 掉,如果有沖突,那么還要把當前遍歷的位置i加入 HashSet 中,然后遍歷 HashSet 中所有的位置,對其調用縮寫函數,此時 pre 對應的值自增1,直到沒有沖突存在為止,參見代碼如下:
class Solution { public: vector<string> wordsAbbreviation(vector<string>& dict) { int n = dict.size(); vector<string> res(n); vector<int> pre(n, 1); for (int i = 0; i < n; ++i) { res[i] = abbreviate(dict[i], pre[i]); } for (int i = 0; i < n; ++i) { while (true) { unordered_set<int> st; for (int j = i + 1; j < n; ++j) { if (res[j] == res[i]) st.insert(j); } if (st.empty()) break; st.insert(i); for (auto a : st) { res[a] = abbreviate(dict[a], ++pre[a]); } } } return res; } string abbreviate(string s, int k) { return (k >= (int)s.size() - 2) ? s : s.substr(0, k) + to_string((int)s.size() - k - 1) + s.back(); } };
Github 同步地址:
https://github.com/grandyang/leetcode/issues/527
類似題目:
Minimum Unique Word Abbreviation
參考資料:
https://leetcode.com/problems/word-abbreviation/