我正在try 实现Rabin-Karp字符串匹配算法,以在字符串haystack中找到字符串needle(返回字符串haystack的索引,其中找到了字符串needle的匹配).我试图在干草堆abc中找到针c时出错了.

下面是运行我的代码在abc中查找c后的输出:

I:0处的hayHash:0和AndleHash:2删除:A和添加:B和新的哈希 是在判断底片之前:1

在I:1处的hayHash:1和AndleHash:2删除:B并添加:C和新的散列 是在判断底片之前:-50

HayHash:51和AndleHash:2

我搞不懂为什么最后一次散列重新计数结果是-50,而不是hayHash2.在这里,hayHashneedleHash都应该是只由char 'c'组成的计算散列,并且两者的值应该相同.但我的代码是重新计算hayHash51(在取消负值之前是-50),而不是2.

对于我的代码中可能存在的错误,有什么建议吗?

以下是我的代码:

private fun find(haystack: String, needle: String): Int {
    if(needle.length > haystack.length) return -1

    val q = 101
    val d = 256
    var needleHash = 0
    var hayHash = 0
    var hash = 1

    for (i in 0..needle.length)
        hash = (hash * d) % q

    for(i in 0..needle.lastIndex) {
        needleHash = (d * needleHash + (needle[i] - 'a')) % q
        hayHash = (d * hayHash + (haystack[i] - 'a')) % q
    }

    for(i in 0..(haystack.length - needle.length)) {
        println("hayHash: $hayHash and needleHash: $needleHash")
        if(hayHash == needleHash) {
            for(j in 0..needle.lastIndex) {
                if(haystack[i + j] != needle[j])
                    break
                if(j == needle.lastIndex)
                    return i
            }
        }
        if(i == haystack.length - needle.length)
            break
        print("at i: $i remove: ${haystack[i]} and add: ${haystack[i + needle.length]}")   
        hayHash = (d * (hayHash - (haystack[i]  - 'a') * hash) + (haystack[i + needle.length]  - 'a')) % q
        println(" and new hash is before checking for negatives: $hayHash")
        if(hayHash < 0)
            hayHash += q
    }

    return -1
}

推荐答案

One part is pre-computing the wrong power of d. The other is multiplying not only the character leaving the window with this power, but the difference from the current hayHash.
Try hayHash = (d * hayHash - ((haystack[i] - 'a') * hash) + (haystack[i + needle.length] - 'a')) % q

Kotlin相关问答推荐

如果一项工作失败,请继续在Kotlin 等待其他工作/子元素完成

相当于roomdb中的DateTime Bigint列的是什么

generic 类实例列表 - 调用采用 T 的函数

在 map 中查找键与在 kotlin 中查找 firstOrNull

修改器的属性是什么,我需要更改以使角变圆且宽度更小?喷气背包组合

Kotlin:使用另一个列表和字母顺序对列表进行排序的有效方法

如何在 Kotlin 中为变量分配另一个变量的值?

从 Kotlin 调用 Java 时可以为空的规则是什么

Picasso 回调

Kotlin - 当表达式返回函数类型

对列表中数字的子集求和

Kotlin 的 isNullOrBlank() 函数是否可以导入 xml 以用于数据绑定

无法在 kotlin android 中以编程方式禁用 EditText

launch 仅从 Kotlin 1.3 开始可用,不能在 Kotlin 1.2 中使用

RecyclerView SnapHelper无法显示第一个/最后一个元素

Gradle:无法连接到 Windows 上的 Kotlin 守护程序

有没有办法在Kotlin中设置一个私有常量

如何在不绑定ViewModel(MVVM)中的UI的情况下使用android导航?

为什么 Kotlin 会收到这样的 UndeclaredThrowableException 而不是 ParseException?

Android Compose 生产准备好了吗?