我可能会对std::set工作感到困惑。我的代码无法正常工作

I might be confused about std::set works. My code isn't working right

本文关键字:工作 代码 我的 常工作 std set      更新时间:2023-10-16

我正在制作一个剽窃检测程序。成品将一句一句地比较两个完整的文本文件;在这一点上,我只是在测试我的算法,以便与句子进行比较,并给出一个介于0和1之间的数字来判断它们的单词有多相似。

我会尝试逐步通过代码,并向您展示问题所在。

指令和函数声明:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <math.h>
#include <set>
double sntnc_cmpr_qtnt(const std::vector<std::string>&, const std::vector<std::string>&);

main获取两个字符串数组,并将它们放入向量中。我知道这似乎没用,但这只是为了我的测试目的。我计算字符串的两个向量(应该是两个句子)之间的句子比较商。

int main (int argc, char* const argv[]) {
    std::string arr1[] = {"Yo", "dawg", "I", "heard", "you", "like", "functions", "so", "we", "put", "a", "function", "inside"};
    std::vector<std::string> str1, str2; 
    for (int i = 0; i < sizeof(arr1)/sizeof(std::string); ++i) 
        str1.push_back(arr1[i]);
    std::string arr2[] = {"Yo", "dawg", "I", "heard", "you", "like", "cars", "so", "we", "put", "a", "car", "inside"};
    for (int i = 0; i < sizeof(arr2)/sizeof(std::string); ++i) 
        str2.push_back(arr2[i]);
    std::cout << sntnc_cmpr_qtnt(str1, str2);
    return 0;
}

这是句子比较商函数。它计算两个句子之间的共同单词数。

不过出了点问题。我的计数(cnt)是158,这显然太高了。我不明白为什么。

double sntnc_cmpr_qtnt(const std::vector<std::string>& s1, const std::vector<std::string>& s2) {
    // Place the words of sentences s1 and s2 each into seperate sets s1_set and s2_set:
    std::set<std::string> s1set, s2set; 
    for (std::vector<std::string>::const_iterator it = s1.begin(); it != s1.end(); ++it) 
        s1set.insert(*it); 
    for (std::vector<std::string>::const_iterator it = s2.begin(); it != s2.end(); ++it) 
        s2set.insert(*it); 
    /* Compute the proportion of words in common between str1_set and str2_set, 
       multiped by 1 over 1 minus the squareroot of the size of the smaller set.
       This is the sentence comparison quotient that is returned.  */ 
    double cnt(0.0);
    for (std::set<std::string>::iterator it1 = s1set.begin(); it1 != s1set.end(); ++it1) { 
        for (std::set<std::string>::iterator it2 = s2set.begin(); it2 != s2set.end(); ++it2) { 
            if ((*it1).compare(*it2))
                cnt += 1.0;
        }
    }
    if (cnt == 0.0) { 
         return 0.0;
    } else {
        double minsz = (double)std::min(s1set.size(), s2set.size());
        return ((1-1/sqrt(minsz))*cnt/minsz);
    }
}

您可以使用==运算符比较两个std::string

但你做的工作也比必要的多得多。一个更快的解决方案是将第一个列表中的所有单词放入集合中,并保存集合的大小。然后将第二个列表中的所有单词放入该集合中。最终设置的大小和保存的大小之间的差异是第二列表中不在第一列表中的单词的数量。(即唯一单词。)当然,保存的大小是第一个列表中唯一单词的数量。

类似的计算会得到第二个列表中唯一单词的数量,以及第一个列表中不在第二个名单中的单词数量。

总执行时间大致与单词总数成比例(实际上,它是n log u,其中u是唯一单词的数量),而您的解决方案与列表大小的乘积成比例。

主要问题在这里:

if ((*it1).compare(*it2))
         cnt += 1.0;

如果它们不相等,这将增加cnt-compare返回0表示相等

此外,您还有一个集合-而不是进行内部循环,只需调用find:

 for (std::set<std::string>::iterator it1 = s1set.begin(); it1 != s1set.end(); ++it1)
    { 
            if (s2set.find(*it1) != s2set.end())
            {
                cnt += 1.0;
            }
    }

我不知道为什么cnt应该是double而不是int