C字符串比较与哈希比较

4
我需要在C语言中将一个字符串与多个其他常量字符串进行比较。我很好奇哪种方法更快,是对我要比较的字符串进行哈希处理并将其与所有其他常量字符串的哈希值进行比较,还是直接将它们作为字符串进行比较。谢谢。
谢谢您的回答,我将会进行许多比较。有没有人能给我一个好的、快速的、低资源消耗的算法来使用?我知道的唯一一个哈希算法是MD5,但我觉得这可能过于复杂了。
我还想补充一点,这些字符串最长可能只有20或30个字符,大部分只有7个左右。
11个回答

10

这个比较是只进行一次还是多次?如果只需要进行一次比较,那么最好直接进行比较。如果你需要对很多字符串与这组常量字符串进行比较,那么用哈希算法可能能在长期内节省时间。

这是一个简单的问题,你可以轻松地用两种方式写出来,并查看哪种方式在代表性输入集上运行更快。


5

前进是很困难的,字符串哈希函数是O(n)的。 字符串比较也是O(n),但是小一些。只有当您可以存储计算出的哈希值并重复使用它们时,您才能取得领先优势。对于两者都是如此。

这里有简单的C哈希函数示例


1
如果你正在将一个字符串与多个字符串进行比较 - 就像问题所问的那样,那会怎么样呢?我认为它不再是O(n),而是O(n^2)对吧? - tushar747

4

哈希值的相等并不保证相等 - 不一致会导致不相等。如果你需要对集合中的许多字符串进行比较,那么哈希是很好的选择 - 如果只需要进行一次比较(我猜这种情况不太可能),那么strcmp将会很好地完成。


没错。请参考 http://stackoverflow.com/questions/186494/ifstr1str2-versus-ifstr1-lengthstr2-length-str1str2/186794#186794 中类似的“优化”。 - Suma

4
如果您想将一个主题字符串与一组其他字符串匹配,您可能考虑使用Aho-Corasick String Matching Algorithm。它使用Trie在单次遍历中将主题与所有目标字符串进行匹配(实现也相当简单)。

3

如果你有一个静态字符串列表,我建议将它们存储在已排序的数组中,然后使用 bsearch 函数来确定该列表中是否存在某个字符串。如果不存在则返回 NULL,如果存在则返回指向该值的指针。这种方法可能比线性搜索或哈希表更快。

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

/* cmp function for qsort and bsearch */
static int pstrcmp(const void *a, const void *b)
{
  return strcmp(*(char * const *)a, *(char * const *)b);
}

/* check an input against the list of known strings */
static char *check_for_match(char *input)
{
  static char *static_list[] = { "one", "two", "three", "four", "five" };
  static int nelems;

  /* this sorts the list, for demonstration purposes, but if the list
     is static then it could be sorted prior to compiling */
  if (! nelems)
  {
    nelems = sizeof(static_list) / sizeof(*static_list);
    qsort(static_list, nelems, sizeof(*static_list), pstrcmp);
  }


  return bsearch(&input, static_list, nelems, sizeof(*static_list), pstrcmp);
}

int main(int argc, char *argv[])
{
  if (check_for_match("should_not_match"))
  {
    printf("Match found.\n");
  } else {
    printf("No match found.\n");
  }

  if (check_for_match("two"))
  {
    printf("Match found.\n");
  } else {
    printf("No match found.\n");
  }
  return EXIT_SUCCESS;
}

1

这要看情况。哈希算法是什么?字符串有多长?平台是什么?

另外请注意,匹配的哈希值并不能保证匹配的字符串相同。


哈希没有假阴性,但有假阳性。 - Steven Sudit

1
如果您的常量字符串在编译时已知,请考虑使用“完美哈希”的概念。
维基百科:对于集合S的完美哈希函数是一种将S中不同元素映射到不同整数的哈希函数,没有冲突。
这个“没有冲突”的东西可以为您节省工作。进一步阅读和实现的可能性包括:

0
直接回答你的问题,如果你只是比较两个字符串(也可以是两个文件、两个视频等),逐个字符比较和哈希都是O(N),没有明显的优势使用哈希方式。
然而,如果该字符串可能会改变,则在第二次运行时哈希将更有效,例如,滚动哈希。
此外,一个字符串/文件的哈希就像一个指纹,你可以直接比较哈希值,下次你想比较另一个字符串是否与这个相同。

0

这很大程度上取决于字符串的长度和哈希函数的复杂性。实施和进行基准测试可能是最好的答案...


0
另一种可能有效的方法是对常量字符串进行排序,并使用二分搜索来查找字符串,这样你只需要最多 log2(n) 次比较(例如,对于1024个字符串只需要10次比较,甚至对于1000000个字符串也只需要20次比较)。 我不知道这种方法是否适用于你的问题,但我在实践中取得了非常好的结果。哈希处理很难做到完美,边缘情况可能会变得非常棘手,而且键值的计算通常也会相当耗费资源。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接