You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义长度比较器引发std::map计数异常问题求助

问题原因与解决:std::map自定义比较器导致计数异常

问题原因

你写的自定义比较器只比较字符串长度,违反了std::map要求的严格弱序规则。std::map判断两个键是否等价的逻辑是:!comp(a,b) && !comp(b,a),如果这个条件成立,map就认为a和b是同一个键。

比如插入"b"时,它和已有的"a"长度相同,comp("a","b")返回false(长度相等),comp("b","a")也返回false,map就判定这两个键等价,直接把"b"的计数加到"a"的条目上,而非创建新条目。这就是"a"计数变成6的原因——所有长度为1的字符串(a、b、c、d、e、f)都被当成同一个键统计,同理长度为2的"ab""bc""cd""de""ef"也被归为同一键,最终导致计数完全异常。

解决方法

有两种可行的修复方式:

方式一:修复比较器,满足严格弱序

当字符串长度相同时,补充字典序比较,确保不同字符串即使长度相同也会被识别为不同键:

// 修改后的比较器:长度优先,长度相同则按字典序排序
auto comp = [](const string& s1, const string& s2) {
    if (s1.length() != s2.length()) {
        return s1.length() < s2.length();
    }
    return s1 < s2; // 长度相同时用字典序区分
};
map<string, int, decltype(comp)> msi(comp);

方式二:分开统计与排序

先用默认的std::map或std::unordered_map完成计数(默认比较器保证键的唯一性),之后再提取键值对按长度排序:

int maximumLength(string s) {
    int n = (int)s.length();        
    unordered_map<string, int> msi; // 也可用map<string, int>
    for (auto i = 0; i < n; i++)    {
        for (auto j = 1; j < n - i + 1; j++)    {
            string tmp = s.substr(i, j);
            msi[tmp] += 1;
        }
    }
    // 将键值对转为vector,按字符串长度降序排序
    vector<pair<string, int>> vec(msi.begin(), msi.end());
    sort(vec.begin(), vec.end(), [](const auto& a, const auto& b) {
        return a.first.length() > b.first.length();
    });
    int res = -1;
    for (const auto& p : vec)  {
        cout << p.first << " " << p.second << endl;
        // if (p.second >= 3)    {
        //     res = (int)p.first.length();
        //     break;
        // }
    }
    return res;
}

原问题代码与输出

原代码

int maximumLength(string s) {
    int n = (int)s.length();        
    auto comp = [&](const string& s1, const string& s2)  { return (int)s1.length() < (int)s2.length(); };
    map<string, int, decltype(comp)> msi(comp);
    // map<string, int, LengthComparator> msi;
    for (auto i = 0; i < n; i++)    {
        for (auto j = 1; j < n - i + 1; j++)    {
            string tmp = s.substr(i, j);
            cout << tmp << endl;
            msi[tmp] += 1;
        }
        debug(msi);
    }
    int res = -1;
    for (auto it = rbegin(msi); it != rend(msi); it++)  {
        cout << it->first << " " << it->second << endl;
        // if (it->second >= 3)    {
        //     res = (int)it->first.length();
        //     break;
        // }
    }
    return res;
}

int32_t main() {
    
    string input{"abcdef"};
    cout << maximumLength(input) << endl;

    return 0;
}

原输出

a
ab
abc
abcd
abcde
abcdef
[msi] = {("a",1),("ab",1),("abc",1),("abcd",1),("abcde",1),("abcdef",1)}
b
bc
bcd
bcde
bcdef
[msi] = {("a",2),("ab",2),("abc",2),("abcd",2),("abcde",2),("abcdef",1)}
c
cd
cde
cdef
[msi] = {("a",3),("ab",3),("abc",3),("abcd",3),("abcde",2),("abcdef",1)}
d
de
def
[msi] = {("a",4),("ab",4),("abc",4),("abcd",3),("abcde",2),("abcdef",1)}
e
ef
[msi] = {("a",5),("ab",5),("abc",4),("abcd",3),("abcde",2),("abcdef",1)}
f
[msi] = {("a",6),("ab",5),("abc",4),("abcd",3),("abcde",2),("abcdef",1)}
abcdef 1
abcde 2
abcd 3
abc 4
ab 5
a 6
-1

内容的提问来源于stack exchange,提问作者kudos3110

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 16:41:05