【问题标题】:I might be confused about std::set works. My code isn't working right我可能对 std::set 的工作感到困惑。我的代码不能正常工作
【发布时间】:2013-11-21 03:31:11
【问题描述】:

我正在制作一个抄袭检测程序。成品会逐句比较两个全文文档;在这一点上,我只是在测试我的算法来比较句子,并给出一个介于 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 接受两个字符串数组并将它们放入向量中。我知道这似乎没用,但这只是为了我的测试目的。我计算两个字符串向量(应该是 2 个句子)之间的句子比较商。

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);
    }
}

【问题讨论】:

  • 您可能想看看string::compare 实际返回的内容。
  • sizeof(std::string)=8 .... 我很确定这是指向字符串的指针的大小
  • 啊,我明白了,sbabbi。哎呀。
  • 如果您愿意,也可以使用set_intersection

标签: c++ string algorithm data-structures std


【解决方案1】:

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

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

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

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

【讨论】:

  • @user2967799 - 那么你将如何计算double minsz = (double)std::min(s1set.size(), s2set.size())
  • @GlennTeitelbaum:每次通过向量时抓取的第一个大小是适当集合的大小。也许我应该更明确一点,尽管这似乎很明显。
  • @rici 是让 OP 考虑的 :) - 但我不确定我是否遵循 - 他想要唯一单词的数量 - 而不是他得分的总单词
  • @GlennTeitelbaum: 对了,在s1(或s2,第二种情况)中插入所有单词后的集合大小就是这样。
  • @rici - 您的解决方案只有一组 - 您优化了 s2 并且只有 s12,其中 s12 是 s1 和 s2 的并集 - 在插入 v2 之前可以通过 s12 大小获得 s1 大小
【解决方案2】:

主要问题在这里:

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

如果它们不相等,这将增加 cnt - 比较返回 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

【讨论】:

    猜你喜欢
    • 2011-10-13
    • 2022-11-19
    • 2019-08-31
    • 2017-10-07
    • 2015-01-13
    • 1970-01-01
    • 1970-01-01
    • 2016-07-29
    • 2019-06-10
    相关资源
    最近更新 更多