[Leetcode] 527. Word Abbreviation 解题报告

博客介绍了LeetCode 527题目的解法,涉及字符串处理和排序。首先对单词按长度和字典序排序,然后计算相邻单词的公共前缀,确定缩写的最小可能长度。如果缩写后长度减少,则采用缩写,否则保留原词。最后按原顺序返回结果。算法复杂度为O(nlogn),空间复杂度为O(n)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

Given an array of n distinct non-empty strings, you need to generate minimal possible abbreviations for every word following rules below.

  1. Begin with the first character and then the number of characters abbreviated, which followed by the last character.
  2. 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.
  3. 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:
  1. Both n and the length of each word will not exceed 400.
  2. The length of each word is greater than 1.
  3. The words consist of lowercase English letters only.
  4. The return answers should be in the same order as the original array.

思路

注意到这样一个事实:凡是有可能发生缩写冲突的单词,必然满足如下两个条件:1)长度相同;2)有相同的前缀。所以我们可以首先对字典中的单词按照长度以及单词本身的字典序进行排序。对于排序后的字典中的每个单词,分别计算它和前面一个单词以及后面一个单词的共同前缀的长度,并取最大值。这个最大值+1其实就是该单词在缩略过程中需要保持原貌的部分的长度。然后判断缩略后长度是否会缩小,如果是,则对该单词进行缩略,否则保持原貌。处理完成之后,恢复单词在原来字典中的顺序即可。

算法的时间复杂度是O(nlogn),空间复杂度是O(n)。

代码

class Solution {
public:
    vector<string> wordsAbbreviation(vector<string>& dict) {
        vector<pair<string, int>> d;       // {string, index}
        for (int i = 0; i < dict.size(); ++i) {
            d.push_back(make_pair(dict[i], i));
        }
        sort(d.begin(), d.end(), PairComp);
        vector<int> pre_common(d.size(), 0), post_common(d.size(), 0);
        for (int i = 1; i < d.size(); ++i) {
            pre_common[i] = commonLength(d[i-1].first, d[i].first);
        }
        for (int i = 0; i + 1 < d.size(); ++i) {
            post_common[i] = commonLength(d[i].first, d[i + 1].first);
        }
        vector<string> ret(dict.size(), "");
        for (int i = 0; i < d.size(); ++i) {
            int least_common = max(pre_common[i], post_common[i]);
            if (least_common + 3 < d[i].first.length()) {
                d[i].first = d[i].first.substr(0, least_common + 1) + 
                             to_string(d[i].first.length() - least_common - 2) + d[i].first.back();
            }
            ret[d[i].second] = d[i].first;
        }
        return ret;
    }
private:
    struct PairCompare {
        bool operator() (const pair<string, int> &a, const pair<string, int> &b) const {
            const string &s1 = a.first;
            const string &s2 = b.first;
            if (s1.length() == s2.length()) {
                if (s1.back() == s2.back()) {
                    return s1 < s2;
                }
                else {
                    return s1.back() < s2.back();
                }
            }
            else {
                return s1.length() < s2.length();
            }
        } 
    } PairComp;
    int commonLength(const string &s1, const string &s2) const {
        if (s1.length() != s2.length() || s1.back() != s2.back()) {
            return 0;
        }
        else {
            for (int i = 0; i < s1.length(); ++i) {
                if (s1[i] != s2[i]) {
                    return i;
                }
            }
            return s1.length();
        }
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值