原題單詞縮寫c++
給出一組 n 個不一樣的非空字符串,您須要按如下規則爲每一個單詞生成 最小 的縮寫。數組
- 從第一個字符開始,而後加上中間縮寫掉的字符的長度,後跟最後一個字符。
- 若是有衝突,就是多個單詞共享相同的縮寫,使用較長的前綴,而不是僅使用第一個字符,直到使單詞的縮寫的映射變爲惟一。 換句話說,最終獲得的縮寫不能映射到多個原始單詞。
- 若是縮寫不會使單詞更短,則不進行縮寫,保持原樣。
只有後綴相同的單詞以前會可能衝突,由於後綴必定保留bash
只有長度相同的會衝突。證實:若是長度不一樣的單詞縮寫到長度相同,那麼縮寫掉部分的長度確定不一樣,那麼中間的數字確定不一樣,那麼這兩個縮寫確定不一樣,不會衝突。ide
因此只有長度相同且後綴相同的單詞纔會衝突,因此把這些可能衝突的分到一個組裏。ui
假設排序後單詞k和k-1的共同前綴長度是x,單詞k和k+1的共同長度是y, 若是最長共同前綴不是x或y,那麼存在一個單詞t,它不在k的兩邊,且共同前綴z知足:z>x,z>y。spa
單詞k+1在k的後面,且共同前綴是y,說明:k+1[y+1]>k[y+1];同理對於k-1有:k-1[x+1]<k[x+1]。而z>x且z>y,那麼這兩個式子對於t也是成立的,也就是在排序後t會在k-1和k+1之間,而這時不可能的,因此出現錯誤假設不成立,不存在這樣的t。code
簡單說,公共前綴越長,排序後越靠近。因此每一個單詞只須要取左右相鄰單詞的共同前綴做爲參考便可。排序
//對單詞排序,按長度、後綴和單詞自己的前後順序
//這樣長度相同、後綴相同的單詞會分到一塊兒
bool wordPairCmp(pair<string, int>& wp1, pair<string, int> &wp2){
int result = (int)wp1.first.length()-(int)wp2.first.length();
if (result!=0) return result<0;
result = wp1.first.back()-wp2.first.back();
if (result!=0) return result<0;
return wp1.first.compare(wp2.first)<0;
}
//求共同前綴的長度
inline int prefixLapCount(string &s1, string &s2){
int c = 0;
while (s1[c] == s2[c]) {
c++;
}
return c;
}
//把一個單詞按指定前綴長度縮寫
inline void wordAbb(string &originalWord, int prefixCount){
int len = (int)originalWord.length();
int cut = len-prefixCount-1;
if (cut<=1) {
return;
}
int destLen = prefixCount+1+log10(cut)+1;
int preIdx = len-cut-2;
string abb(destLen,' ');
for (int i = 0; i<=preIdx; i++) {
abb[i] = originalWord[i];
}
abb[destLen-1] = originalWord.back();
//中間縮寫的數字部分,沒有使用atoi等方法而是直接實現,效率會快很對
for (int i = destLen-2; i>preIdx; i--) {
abb[i] = cut%10+'0';
cut = cut/10;
}
originalWord = abb;
}
vector<string> wordsAbbreviation(vector<string> &dict) {
//使用pair的緣由是爲了記錄單詞在原數組裏的索引位置,這樣排序後,還能夠再重置到輸入時的順序
vector<pair<string, int>> wordPairs;
int i = 0;
for (auto &w : dict){
wordPairs.push_back({w,i});
i++;
}
sort(wordPairs.begin(), wordPairs.end(), wordPairCmp);
int size = (int)wordPairs.size();
int preLapCount = 0; //和前一個重疊的字符個數
for (int i = 0; i<size; i++) {
int nextLapCount = 0;
//由於沒有使用分組,即沒有用多維數組,而是單個數組,因此須要作先後斷定,長度不一樣或者後綴不一樣,則共同前綴就不考慮了,直接是0.
//這裏會影響效率,由於大部分比較都是無心義的或者說跟排序的工做有重複
if (i<size-1 &&
wordPairs[i].first.length() == wordPairs[i+1].first.length() &&
wordPairs[i].first.back() == wordPairs[i+1].first.back()) {
nextLapCount = prefixLapCount(wordPairs[i].first, wordPairs[i+1].first);
}
wordAbb(wordPairs[i].first, max(preLapCount, nextLapCount)+1);
preLapCount = nextLapCount;
}
for (auto &p : wordPairs){
dict[p.second] = p.first;
}
return dict;
}
複製代碼