重载 C++ 集插入

Overload C++ set insert

是否可以重载字符串集中的比较运算符,使其将编辑距离 <= 1 的两个元素定义为相同?

这是我失败的尝试:

#include <string>
#include <set>
#include <vector>
#include <iostream>

using namespace std;

int min(int x, int y, int z) 
{
   return min(min(x, y), z);
}

int getEditDist(string& str1, string& str2, int m, int n)
{
    if (str1[m-1] == str2[n-1])
        return getEditDist(str1, str2, m-1, n-1);
    return 1 + min ( getEditDist(str1,  str2, m, n-1),
                     getEditDist(str1,  str2, m-1, n),
                     getEditDist(str1,  str2, m-1, n-1)
        );
}


class editDist
{
public:
    bool operator () (string& str1, string& str2)
        {
            return(getEditDist(str1, str2, str1.length(), str2.length()) <= 1);
        }
};


int main(int argc, char* argv[])
{

    string id1 = "AAA";
    string id2 = "BBB";
    string id3 = "BAB";
    set<string,editDist> my_set;
    //set<string> my_set;
    set<string,editDist>::const_iterator itr;
    //set<string>::const_iterator itr;
    my_set.insert(id1);
    my_set.insert(id2);
    my_set.insert(id3);
    for(itr = my_set.begin();itr != my_set.end();++itr) cout<<*itr<<endl;
    return(0);
}

我什至不确定它的编码是否正确,因为它无法编译。

编译失败有两个原因:

  • 你递归调用你的 min 函数但是参数太少
  • getEditDist 和 operator() 的参数必须是常量

除此之外,您在 getEditDist 中的递归将永远不会完成。

即这将编译:

#include <string>
#include <set>
#include <vector>
#include <iostream>
#include <algorithm>

int min3(int x, int y, int z) 
{
   return std::min(std::min(x, y), z);
   // Or just use `std::min({x, y, z})` if you have C++11 available
}

int getEditDist(const std::string& str1, const std::string& str2, int m, int n)
{
    if (str1[m-1] == str2[n-1])
        return getEditDist(str1, str2, m-1, n-1);

    return 1 + min3(
        getEditDist(str1,  str2, m, n-1),
        getEditDist(str1,  str2, m-1, n),
        getEditDist(str1,  str2, m-1, n-1));
}

class editDist
{
public:
    bool operator () (const std::string& str1, const std::string& str2)
    {
        return(getEditDist(str1, str2, str1.length(), str2.length()) <= 1);
    }
};

int main(int argc, char* argv[])
{

    std::string id1 = "AAA";
    std::string id2 = "BBB";
    std::string id3 = "BAB";
    std::set<std::string, editDist> my_set;
    //set<string> my_set;
    std::set<std::string, editDist>::const_iterator itr;
    //set<string>::const_iterator itr;
    my_set.insert(id1);
    my_set.insert(id2);
    my_set.insert(id3);
    for(itr = my_set.begin(); itr != my_set.end(); ++itr)
        std::cout << *itr<< std::endl;

    return 0;
}

但是当你运行它时它会导致堆栈溢出。你将需要 更改 getEditDist 使其停止。

TLDR:不,不可能做你想做的事。

详情:

  • 你可以定义一个比较器 d(a,b) ≤ 1 ⇒ a ∼ b;

  • 唯一有效的比较器,是∀(a,b),a∼b,没什么用;

  • 然而,not 可以定义一个比较器 d(a,b) ≤ 1 ⇔ a ∼ b 这正是您想要的.

比较器定义了字符串的排序和 classes 的等价性。如果您希望任何两个编辑距离 ≤ 1 的元素处于相同的等价 class,这意味着任何编辑距离 ≤ 2 的元素也处于相同的等价 class。我们可以继续对任何可能的编辑距离进行推理,因此所有字符串必须处于相同的 class 等价:

 struct always_equal_less {
   bool operator()(std::string const& x, std::string const& y) const {
     return false;
   }
 };

更正式的解释

std:set<Key,Compare,Allocator> must follow the Compare概念的Compare参数,即它必须定义严格的弱排序关系。它必须具有以下属性:

  • 传递性,(a≺b∧b≺c)⇒a≺c;

  • 非自反性,¬(a ≺ a);

  • 不对称,(a ≺ b) ⇒ ¬(b ≺ a);

  • 不可比传递性(a∼b)∧(b∼c)⇒(a∼c).

我用 a∼b 表示 ¬(a ≺ b) ∧ ¬(b ≺ a)。

假设我们有这样一个关系≺,它有额外的属性,对于编辑距离小于或等于1的任何两个元素都等于:d(a,b)≤1⇒a ∼ b.

我们可以证明唯一正确的关系是比较所有字符串是否相等:∀(a,b), a∼ b:

  • 让我们取编辑距离为2的两个元素,d(a,b) = 2。我们可以找到第三个元素c,例如:d(a,c) = 1和d(c ,b) = 1。我们有 a∼c 和 c∼b。不可比性的传递性给出:a∼b。这意味着任何两个编辑距离为 2 的元素也被认为是相等的:∀(a,b), d(a,b) = 2, a ~ b.

  • 你可以继续推理d(x,y)=3, d(x,y)=4。这表明任何给定的字符串对必须比较相等。

我们得到(没用的)关系∀(a,b), a ~ b.

因此无法定义 d(a,b) ≤ 1 ⇔ a ∼ b 的比较器。