Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 高效的字符串搜索算法?_String_Scala_Complexity Theory_Big O_Time Complexity - Fatal编程技术网

String 高效的字符串搜索算法?

String 高效的字符串搜索算法?,string,scala,complexity-theory,big-o,time-complexity,String,Scala,Complexity Theory,Big O,Time Complexity,我现在要道歉,因为这个问题在我脑海里听起来很愚蠢,我可能忽略了一些非常明显的事情。无论如何 好的,我在自学scala,作为学习练习,我决定实现一个方法,确定一个字符串是否包含另一个更小的字符串。我做的第一件事是使用naive版本,在该版本中,我查看字符串的每个字母,并开始向前检查每个字符是否匹配。那很好。然后我决定实施一种更有效的方法,这就是我想到的(不包括特殊情况): //如果a是b的子字符串,则返回true def是_sub(a:String,b:String):布尔={ 对于(i你的算法仍

我现在要道歉,因为这个问题在我脑海里听起来很愚蠢,我可能忽略了一些非常明显的事情。无论如何

好的,我在自学scala,作为学习练习,我决定实现一个方法,确定一个字符串是否包含另一个更小的字符串。我做的第一件事是使用naive版本,在该版本中,我查看字符串的每个字母,并开始向前检查每个字符是否匹配。那很好。然后我决定实施一种更有效的方法,这就是我想到的(不包括特殊情况):

//如果a是b的子字符串,则返回true
def是_sub(a:String,b:String):布尔={
对于(i你的算法仍然是O(nm)

设m为模式的长度,n为搜索字符串的长度

在搜索字符串中的每个(n-m)位置,您都在生成一个子字符串并计算其哈希代码。每个子字符串都需要迭代m个字符

复杂性不仅取决于您编写的代码,还取决于您调用的代码。

您的算法仍然是O(NM)

设m为模式的长度,n为搜索字符串的长度

在搜索字符串中的每个(n-m)位置,您都在生成一个子字符串并计算其哈希代码。每个子字符串都需要迭代m个字符


复杂性不仅取决于您编写的代码,还取决于您调用的代码。

您发布的代码不能保证是正确的。如果两个字符串相等,则它们的哈希代码必须相同,但反之不一定正确。可以找到不同字符串的字符串对,但ich具有相同的哈希代码。因此,如果您找到与要搜索的字符串具有相同哈希代码的子字符串,则函数可能会返回不正确的答案

此外,您的复杂性分析有点不正确。为长度为k的字符串计算哈希代码需要时间O(k)(假设您有一个半途而废的哈希函数!),因此这意味着在循环的每次迭代中,您都将进行O(n)个工作来计算所取子字符串的哈希代码。既然您这样做了O(m)次,总时间复杂度为O(mn),而不是O(m-n)

但是,您所做的与密切相关,它确实基于哈希字符串。为了避免在每次迭代中进行O(n)运算,该算法使用了一个滚动哈希函数,该函数可以在O(1)时间内轻松地从一个子字符串更新到下一个子字符串。它还有一个额外的检查,这样,如果当前哈希代码与子字符串的哈希代码匹配,该算法实际上会检查每个字符以确保它们匹配。在最坏的情况下,该算法需要时间O(mn),但在平均情况下要快得多(时间O(m+n))


希望这有帮助!

您发布的代码不能保证是正确的。如果两个字符串相等,则它们的哈希代码必须相同,但反之不一定正确。可以找到不同字符串但具有相同哈希代码的字符串对。因此,您的函数可能返回inco如果找到与要搜索的字符串具有相同哈希代码的子字符串,请更正答案

此外,您的复杂性分析有点不正确。为长度为k的字符串计算哈希代码需要时间O(k)(假设您有一个半途而废的哈希函数!),因此这意味着在循环的每次迭代中,您都将进行O(n)个工作来计算所取子字符串的哈希代码。既然您这样做了O(m)次,总时间复杂度为O(mn),而不是O(m-n)

但是,您所做的与密切相关,它确实基于哈希字符串。为了避免在每次迭代中进行O(n)运算,该算法使用了一个滚动哈希函数,该函数可以在O(1)时间内轻松地从一个子字符串更新到下一个子字符串。它还有一个额外的检查,这样,如果当前哈希代码与子字符串的哈希代码匹配,该算法实际上会检查每个字符以确保它们匹配。在最坏的情况下,该算法需要时间O(mn),但在平均情况下要快得多(时间O(m+n))


希望这有帮助!

你考虑过哈希的时间复杂性吗?@ Alx23 -子串是java/Scala中的O(1)。二极管-我认为哈希的时间复杂度是固定的,但是我猜我错了。@ USER 439 99- Substring是java中的O(1),但是java 7更新6,首选是复制(O)(n)。.See.Gotcha,是的。谢谢。我现在仍然使用java 6,不过我想这还不适用于我(尽管很高兴知道我什么时候更新)有趣的东西,无论如何。你可以绕过O(n)通过定义哈希函数只对原始字符串进行操作,并传入偏移量和长度来解决子字符串问题哈希函数很可能会有冲突,所以当你得到匹配的散列时,你必须做一个蛮力相等的检查来确认潜在的匹配。基本上,你的哈希函数越好,冲突就越少,但是哈希函数也一定会更复杂。你考虑哈希的时间复杂性吗?@ Alx23—Substringjava/scala.Diode中的O(1)-我原以为散列的时间复杂度是常数时间,但我猜我错了。@user439299-子字符串在java中是O(1),但在java 7 update 6中,首选的是在O(n)中进行复制。请看。明白了,是的。谢谢。我现在仍然使用java 6,尽管我猜这不适用于我(尽管知道何时更新是件好事)无论如何,你可以考虑一些有趣的事情。你可以通过定义哈希函数来绕过O(n)子字符串问题,只对原始字符串进行操作,并传入偏移量和长度。正如其他人指出的,O(1)哈希函数类似于
// return true if a is a substring of b
def is_sub(a: String, b: String) : Boolean = {
  for(i <- 0 until b.length-a.length) { // O(n-m)
    if(a.hashCode == b.substring(i,a.length+i).hashCode) return true // O(1) + O(1) + O(1)
  }
  return false
}