【问题标题】:c++ string compare algorithm [closed]c ++字符串比较算法[关闭]
【发布时间】:2012-10-10 16:32:35
【问题描述】:

你最好的字符串比较算法是什么?

我发现 O(n)

#include <string>

bool str_cpmr(char* str1, char* str2)
{
    int l1 = strlen(str1), l2 = strlen(str2) ;          

    if(l1 != l2)
        return false;

    for(int i = 0 ; i < l1 ; i++)
        if(str1[i] != str2[i])
            return false ;

    return true ;
}

我想知道是否还有其他/更好的解决方案。

另外,如何准确测试?

我建议比较

  • 100 个匹配项
  • 100 个字符串相差一个字符交换

还有更多的测试字符串比较吗?

在 stl c++ (slt string::compare) 中怎么样?

谢谢!!!!!!

【问题讨论】:

  • [被 c++ 标签混淆] 我可能是错的,但不是有 std::string::compare 吗?您是否只为strlen 包含&lt;string&gt;?使用std::strings!
  • 比较长度似乎是一种浪费,因为您的 for 循环只能检查 EOS。
  • 为什么不拥有 2 个 std::string 对象然后做 s1 == s2 而不是重新发明轮子。
  • 你不需要strlen。这是重复工作。
  • @tenfour:这仍然是 O(n),它只是有一个更高的常数乘数。

标签: c++ string algorithm stl compare


【解决方案1】:

你的函数是 O(n),但仍然需要大约两倍的时间——strlen 遍历字符串以找到长度,然后(假设它们的长度相同)你遍历字符串再次比较人物。

取而代之的是,我会遍历字符串,直到出现不匹配或两个字符串的结尾。如果达到不匹配,则返回 false。当且仅当您(同时)到达两个字符串的末尾且没有任何不匹配时,您才返回 true。

【讨论】:

  • +1:当然可以,但是在此之前您还可以做一件事:在开始遍历之前比较传入的 指针。如果它们是相同的地址,则跳过所有内容并返回 true。
  • @WhozCraig,如果确实有可能将字符串与自身进行比较,这将节省时间;但是在我编写的代码和我看过的代码中,即使使用string interning,这种可能性也很低,以至于像这样的预检查是净损失。例如,如果您测试 1000 个 10 个字符的字符串,其中 1 个与自身进行比较,您节省了大约 9 次操作,浪费了大约 999 次,净浪费了 990 次操作。
  • @JerryCoffin 关于字符串结尾:你如何测试字符串结尾?tks!
  • @jwpat7 我完全同意概率权重。因此,这样的前置条件检查非常专业。如果您正在编码的特定算法设计可能会传递相同的指针两次,那么它就是一个胜利,否则它可能不会,并且 cmp 指令将是一个净操作损失。当然,它仍然是 O(1)+O(n),因此也是 O(n)。如果那个额外的 cmp 是相关的,那么你应该首先在 asm 中写这个。
  • @madptr:包含'\0'的字节表示字符串的结束。
【解决方案2】:

从逻辑上讲,很难看出如何在少于 O(n) 的时间内检查字符串中的所有值是否存在单个字符不匹配 - 假设您没有关于字符串的其他信息。

如果这是一个真实的应用程序,并且您对字符串和差异类型有一定的了解,如果您知道它包含长度为“N”的序列(例如零件或电话),则可以通过首先检查每个第 N 个字符来平均做得更好数字。

edit:请注意,这仍然是 O(n),O() 仅描述缩放的功率,它只是 O(n/N),仍然是 O(n)。如果您将字符串延长 10 倍,则检查每 N 个条目仍然需要 10 倍的时间。

【讨论】:

    【解决方案3】:

    你最好的字符串比较算法是什么?

    template< class T, class Alloc > bool operator==( basic_string<T,Alloc>& lhs, basic_string<T,Alloc>& rhs );.

    它只使用源代码的两个字符来比较两个字符串:

    a==b;
    

    这是一个非智能的答案,用 C 语言编写:

    bool str_cpmr(char* str1, char* str2)
    {
      while( *str1 && *str2 && *str1++ == *str2++ )
        ;
      return *str1 == *str2;
    }
    

    这正是一个循环,所以显然是 O(n),其中 n 是较短字符串的长度。此外,它很可能编译为恰好 2n 次内存提取。您可以使用专门的字符串指令更快(因此调用 strcmp() 可能会比这更快),但在直接 C 中您可能不会更快。

    【讨论】:

      【解决方案4】:

      您改进后的功能可能如下所示:

      bool str_cpmr(char* str1, char* str2)
      {
          if (NULL == str1 || NULL == str2) return false;
      
          while (*str1 && *str2) {
              if (*str1++ != *str2++) {
                  return false;
              }
          }
      
          return *str1 || *str2 ? false : true;
      }
      

      【讨论】:

      • 你可以做得更好:for (; *str1 == *str2 && *str1; ++str1, ++str2;){} return *str1 == *str2; // 每个循环只有两个比较而不是三个。
      【解决方案5】:

      如果没有关于字符串性质的额外信息,没有什么比 O(n) 更好的了,其中 n 是(较短的)字符串的长度。

      您不能进行少于 n 次的比较!给我一个可以通过 n-1 比较来完成的算法。那么在字符串中必须有一个位置,算法无法判断字符是否不同。这样我可以给你一个例子,你的算法与 n-1 比较失败。

      您只能通过一个常数因素来改进这一点。这还将考虑其他信息,例如如果您知道底层硬件比较 32 位值比 8 位值快,那么比较四个字符的块而不是逐个字符比较会更好。你不会做得更好。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-01-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多