【问题标题】:Rolling Hash Algorithm for Rabin-Karp Algorithm Java用于 Rabin-Karp 算法 Java 的滚动哈希算法
【发布时间】:2023-03-09 00:55:01
【问题描述】:

我一直在尝试理解算法类的 Rabin-Karp 算法。我在理解它时遇到了很多麻烦,所以我尝试实现它(我实际上不必实现它)。我想我正确理解了除了滚动哈希函数之外的所有内容。我的算法目前仅在模式 char[] 与文本 char[] 的开头匹配时才有效。我无法弄清楚我的滚动哈希哪里出错了。如果有人能指出错误的方向,我将非常感激。

结果 文本“我的测试字符串” 模式“我的” - 这是匹配的返回 模式“测试” - 这表明不匹配

private static int int_mod(int a, int b)
{
    return (a%b +b)%b;
}

public static int rabin_Karp(char[] text, char[] pattern)
{
    int textSize = text.length;
    int patternSize = pattern.length;
    int base = 257;
    int primeMod = 1000000007;

    if(textSize < patternSize) 
    return -1;n
    int patternHash = 0;
    for(int i = 0; i < patternSize; i++) 
        patternHash += int_mod(patternHash * base + pattern[i], primeMod);//This is only done once so put method here           
        System.out.println("patternHash: " + patternHash);
    //calculate the value of the first hash
    int segmentHash = 0;
    for(int i = 0; i < patternSize; i++) //remove this, this will be duplicate
        segmentHash += int_mod(segmentHash * base + text[i], primeMod);
        System.out.println("segmentHash: " + segmentHash);

    Boolean firstMatch = false;
    if(segmentHash == patternHash) 
    {
        firstMatch = true;
        for(int i=0; i<pattern.length; i++)
        {
            if(pattern[i] != text[i])
            firstMatch = false;
        }
    }
    if (firstMatch == true)
    {
        return 0;
    }

    for(int i=1; i<textSize - patternSize; i++)
    {
        segmentHash += int_mod(segmentHash * base + text[i + pattern.length -1],primeMod);
        segmentHash -= int_mod(segmentHash * base + text[i-1], primeMod);
        System.out.println("segmentHash: " + segmentHash);

        if(segmentHash == patternHash) 
        {
            firstMatch = true;
            for(int j=0; j<pattern.length; j++)
            {
                if(pattern[j] != text[j])
                    firstMatch = false;
            }
        }
        if (firstMatch == true)
        {
            return i;
        }
    }

    return -1;
}

【问题讨论】:

    标签: java algorithm hash rabin-karp


    【解决方案1】:

    您的代码中有几个基本问​​题。

    第一个在这里:patternHash += int_mod(patternHash * base + pattern[i], primeMod); 它在其他几个地方重复。

    第二个是计算划船哈希:

        segmentHash += int_mod(segmentHash * base + text[i + pattern.length -1],primeMod);
        segmentHash -= int_mod(segmentHash * base + text[i-1], primeMod);
    

    这两个错误都可以轻松修复。但是,我建议您更好地理解代码背后的逻辑,而不是仅仅从某个地方复制它。您使用的散列算法基于多项式,因此请尝试查看在该级别上发生了什么。甚至可以手动编写一些示例——它们在调试代码时会很有用。

    还要注意整数溢出会出现问题:
    - int 可以存储高达 ~20 亿的数字;
    - 您的主要模块约为 10 亿,因此哈希值(特别是 patternHash 和 segmentHash)可以达到该数字;
    - 你的基地是int base = 257;

    因此,表达式segmentHash * base 可以达到~2570 亿,这肯定是整数溢出。

    【讨论】:

    • 您的回答非常好,但我已经阅读了更多关于此的内容,并且我意识到我的问题是我不明白我没有正确理解数学。我将对此进行更多阅读,但如果您知道我在哪里可以找到“傻瓜”的解释,我将不胜感激。
    • 嗯,我知道一些书,它们介绍了这个以及更多的算法(例如,算法简介,或简单的 CLRS)。但是,我不确定您是否可以在网上免费找到它们。如果你愿意,我可以尝试用一些关于基础数学的基本解释来修改我的答案(我正准备把它写成评论,但我需要更多空间)。
    • 我将不胜感激。我正在上算法课。我已经参加了考试,我认为我做得很好,但我无法弄清楚这一点,这让我很困扰。
    猜你喜欢
    • 2016-09-06
    • 2017-07-27
    • 1970-01-01
    • 2012-01-18
    • 1970-01-01
    • 2018-11-22
    • 2013-12-23
    • 2021-05-26
    • 2016-08-17
    相关资源
    最近更新 更多