【问题标题】:A good algorithm for string comparing (like Total Commander compare)一个很好的字符串比较算法(比如 Total Commander 比较)
【发布时间】:2013-04-16 09:25:55
【问题描述】:

我想在 C++ 中创建一个字符串比较脚本。
Total Commander 文件比较功能不错:


这个算法是如何工作的?
有人可以分享这个功能的 sn-p 吗?

【问题讨论】:

  • 您听说过diffLCS吗?
  • 也许可以尝试使用类似汉明距离的方法。也阅读这篇文章stackoverflow.com/questions/6163611/compare-two-files
  • @Androidy 这完全不相关。
  • 为什么不@AlexeyFrunze?请解释一下汉明是为了比较单词。您也可以将其应用于缓冲区。不像 LCS 那样理想。
  • @Androidy 这个问题是关于检查两个文件是否相同。这里的问题有所不同,OP 想要查看发生了什么变化以及在哪里发生了变化,而不仅仅是检测到发生了一些变化。

标签: c++ string algorithm compare string-comparison


【解决方案1】:

我不能告诉你,总司令是做什么的。也许可以拆开它并尝试追踪技术。

但是一个常见的算法是这个:

http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm

一种字符串搜索算法。它肯定也有助于比较。

另外请参考这篇文章: c++ string compare algorithm

最好的问候

【讨论】:

  • 您建议如何将 KMP 应用于 OP 的问题?
  • KMP : 字符串搜索算法 = 字符串(子)字符串匹配算法。否定它将使字符串“不匹配”算法。对吗?
  • 我没有关注你。你能举一个例子,说明如何使用 KMP 找到两个给定字符串之间的单词 ate 更改为 eat,然后删除单词 on
  • 你好。不,我必须承认。现在不行。但如果你让我花点时间,我会尝试开发一种解决方案。
【解决方案2】:

您可以使用 diff 或 LCS 算法进行此类比较。

下面是它的简单 C 实现:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

int lcs(const char* s1, const char* s2)
{
  size_t l1 = strlen(s1), l2 = strlen(s2);
  size_t sz = (l1 + 1) * (l2 + 1) * sizeof(size_t);
  size_t w = l2 + 1;
  size_t* dpt;
  size_t i1, i2;

  if (sz / (l1 + 1) / (l2 + 1) != sizeof(size_t) ||
      (dpt = malloc(sz)) == NULL)
  {
    printf("Not enough memory\n");
    return EXIT_FAILURE;
  }

  for (i1 = 0; i1 <= l1; i1++)
    dpt[w * i1 + 0] = 0;
  for (i2 = 0; i2 <= l2; i2++)
    dpt[w * 0 + i2] = 0;

  for (i1 = 1; i1 <= l1; i1++)
    for (i2 = 1; i2 <= l2; i2++)
    {
      if (s1[l1 - i1] == s2[l2 - i2])
      {
        dpt[w * i1 + i2] = dpt[w * (i1 - 1) + (i2 - 1)] + 1;
      }
      else if (dpt[w * (i1 - 1) + i2] > dpt[w * i1 + (i2 - 1)])
      {
        dpt[w * i1 + i2] = dpt[w * (i1 - 1) + i2];
      }
      else
      {
        dpt[w * i1 + i2] = dpt[w * i1 + (i2 - 1)];
      }
    }

  i1 = l1; i2 = l2;
  for (;;)
  {
    if ((i1 > 0) && (i2 > 0) && (s1[l1 - i1] == s2[l2 - i2]))
    {
      printf("%c", s1[l1 - i1]);
      i1--; i2--; continue;
    }
    else
    {
      if (i1 > 0 &&
          (i2 == 0 || dpt[w * (i1 - 1) + i2] >= dpt[w * i1 + (i2 - 1)]))
      {
        printf("-%c", s1[l1 - i1]);
        i1--; continue;
      }
      else if (i2 > 0 &&
               (i1 == 0 || dpt[w * (i1 - 1) + i2] < dpt[w * i1 + (i2 - 1)]))
      {
        printf("+%c", s2[l2 - i2]);
        i2--; continue;
      }
    }

    break;
  }
  printf("\n");

  free(dpt);
  return EXIT_SUCCESS;
}

int main(int argc, char** argv)
{
  const char *s1, *s2;
  if (argc == 3)
  {
    s1 = argv[1]; s2 = argv[2];
  }
  else
  {
    printf("Usage:\n  lcs-diff.exe <string1> <string2>\n\n");
    s1 = "I ate apple on yesterday"; s2 = "I eat apple yesterday";
    printf("Sample comparison:\n\n  \"%s\" vs \"%s\":\n\n", s1, s2);
  }

  return lcs(s1, s2);
}

输出(ideone):

Usage:
  lcs-diff.exe <string1> <string2>

Sample comparison:

  "I ate apple on yesterday" vs "I eat apple yesterday":

I +eat-e apple -o-n- yesterday

【讨论】:

    【解决方案3】:

    从头开始,我会这样处理这个问题(伪代码):

    String[] sarr1 = string1.split();
    
    for (int i1 =0; i1<sarr1.length; i1++) {
      if (!string2.contains(sarr[i1]) {
        markWordRed(string1, sarr[i1]);
      }
    }
    
    String[] sarr2 = string2.split();
    for (int i2 =0; i2<sarr2.length; i2++) {
      if (!string1.contains(sarr[i2]) {
        markWordRed(string2, sarr[i2]);
      }
    }
    

    从那个开始还可以:

    • 检查单词的顺序,而不仅仅是它们是否存在

    • 检查每个未找到的单词与第二个字符串中所有未找到的单词的相似度并显示字母差异

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-05
      • 2011-12-26
      • 1970-01-01
      • 1970-01-01
      • 2013-05-06
      • 1970-01-01
      • 1970-01-01
      • 2011-02-21
      相关资源
      最近更新 更多