【问题标题】:Check if a string is available in a bigger string of length 100,000 [duplicate]检查字符串是否在长度为 100,000 的更大字符串中可用 [重复]
【发布时间】:2012-09-14 05:00:09
【问题描述】:

可能重复:
What is the fastest substring search algorithm?

如何在 C++ 或 Java 中检查一个字符串是否存在于长度为 100,000 个字符的较大字符串中?

我知道一个方法str.find("sub_string");,但它不能处理这么大的字符串。 最长执行时间为 1 秒。

我需要查找的子字符串也可以是 50,000!

【问题讨论】:

  • 你想要哪个? C ++或Java或两者兼而有之?每个人的答案都不一样。
  • 您不可能期望任何算法在一秒钟内执行此操作。执行时间必须在 O(n) 到 O(n^2) 之间,或者更糟。
  • 为什么这是一个 SO 问题?只需使用您喜欢的string search algorithm 编写满足您需要的代码。正如所问的,这太模糊了,无法回答,因为它没有给我们提供足够的信息来选择合适的算法。 (从搜索到搜索,子串有变化吗?字符串是不是均匀分布的字符?子串是否包含稀有的内部子串?等等。)
  • c++ 或 java...它们中的任何一个都可以工作...
  • @Drise 绝对是O(n)。但是无论如何,100,000 应该可以在 1 秒内完成。

标签: java c++ string


【解决方案1】:

在 C 或 C++ 中,您只需使用 malloc 即可获得 100,000 字节的块。用你的数据填充它。大海捞针,可以使用以下代码:

void *mem_mem(void *haystack, int haystack_len, void *needle, int needle_len)
{
  const char *begin;
  const char *const last_possible
    = (const char *) haystack + haystack_len - needle_len;

  if (needle_len == 0)
    return (void *) &((const char *) haystack)[needle_len - 1];

  for (begin = (const char *) haystack; begin <= last_possible; ++begin)
    if (begin[0] == ((const char *) needle)[0] &&
    !memcmp ((const void *) &begin[1],
         (const void *) ((const char *) needle + 1),
         needle_len - 1))
      return (void *) begin;

  return NULL;
}

在任何相当现代的平台上,这将在几分之一秒内找到 100,000 个字节中的任何子字符串。您可以修改它以使用char * 类型。如果您在同一个 haystack 中进行多次搜索,请尝试仅计算一次 haystack 长度。不需要时不要拨打strlen

如果您的干草堆包含许多重复的第一个字符或针的第一个字符,这将是非常不理想的。例如,在“aaaaaaaaaaaaaaaaaaaaaaaaaaaaqaaaa..”中搜索“ab”(或者更糟的是,在“abababababababab...abc...”中搜索“abc”)会很慢。但是您没有提供足够的详细信息让我们确定最佳实施方式。

问题的重点完全有可能是编写具有最佳最坏情况性能的算法。如果是这样,这可能不是“正确”的答案。可以想象一个由所有 a 后面跟着一个 b 结尾的干草堆,以及一个由所有 a 后面跟着一个结尾的单个 b 组成的针。在那种情况下,这个算法可能需要很长时间。

【讨论】:

  • 对于一个可怕的问题,我认为这是最合理的答案,尤其是重复字符位。
  • 我怀疑是在线法官,所以测试用例可能会包含类似needle = a^9999b, haystack=a^100000 的内容,这在使用朴素算法的时间限制内是不可行的。
  • @DanielFischer 好点。问题的重点完全有可能是编写具有最佳最坏情况性能的算法。如果是这样,这可能不是“正确”的答案。
  • 您应该将your comment 合并到答案中以涵盖该案例:D
  • @DanielFischer:你是对的。完成。
【解决方案2】:

这在我适中的第一代英特尔 iMac 上几乎立即完成(4 毫秒)。我将搜索字符串放在两个 100,000 个字符的块之间,以防 java 向后搜索。

StringBuilder builder = new StringBuilder();
for (int i = 0; i < 100000; i++) {
    builder.append((char) i);
}
builder.append("sub_string");
for (int i = 0; i < 100000; i++) {
    builder.append((char) i);
}
String maxString = builder.toString();
long t1 = System.currentTimeMillis();
System.out.println(maxString.contains("sub_string"));
long t2 = System.currentTimeMillis();
System.out.println(t2 - t1);

输出

true
4

【讨论】:

    【解决方案3】:

    假设java:

    String.contains("stringtofind");
    

    是一种查找字符串是否存在于另一个字符串中的方法,javadoc

    【讨论】:

    • @r20rock:我没有用大字符串测试它。但是,javadoc 没有指定任何限制,所以它应该可以工作。
    • 添加更多?不能帮助您更快或更好地获得答案。只是让我想狠狠地捉弄你。
    • 请记住..string.contains() 是区分大小写的检查
    【解决方案4】:

    在java中查找String内容的三种方式。

    String.contains("charSequence");
    String.contentEquals("charSequence");
    String.contentEquals("StringBuffer"); 
    

    您可以通过 Java 规范获得最大长度为 Integer.MAX_VALUE(始终为 2147483647 (2^31 - 1))的字符串。

    【讨论】:

      猜你喜欢
      • 2015-07-07
      • 1970-01-01
      • 2023-03-31
      • 2014-03-03
      • 2012-10-23
      • 2017-08-19
      • 2017-12-24
      • 2019-06-06
      • 2012-03-26
      相关资源
      最近更新 更多