Rabin-Karp算法Java的滚动哈希算法

时间:2013-09-04 01:53:29

标签: java algorithm hash rabin-karp

我一直在努力了解算法类的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;
}

1 个答案:

答案 0 :(得分:2)

您的代码中存在一些基本问题。

第一个是: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亿,所以哈希(特别是patternHashsegmentHash)可以达到那个数字;
  - 您的基数为int base = 257;

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