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 如何在Rabin-Karp算法的滚动哈希中加入mod?_String_Algorithm_String Matching_Rabin Karp - Fatal编程技术网

String 如何在Rabin-Karp算法的滚动哈希中加入mod?

String 如何在Rabin-Karp算法的滚动哈希中加入mod?,string,algorithm,string-matching,rabin-karp,String,Algorithm,String Matching,Rabin Karp,我试图用mod实现Rabin-Karp算法。我正在使用的哈希函数是: H1= c1*a^k-1 + c2*a^k-2 +c3*a^k-3 +…+ck*a^0 这里cx是字符的ASCII值。要滚动它,我首先通过减去它来删除第一项,然后乘以a,再通过乘以^0来添加新项 现在的问题是处理大值,我使用了mod操作,但这样做我无法正确地滚动它。我的代码如下: public class RabinKarp { private static final int base = 26; private stat

我试图用mod实现Rabin-Karp算法。我正在使用的哈希函数是:

H1= c1*a^k-1 + c2*a^k-2 +c3*a^k-3 +…+ck*a^0
这里cx是字符的ASCII值。要滚动它,我首先通过减去它来删除第一项,然后乘以a,再通过乘以^0来添加新项

现在的问题是处理大值,我使用了mod操作,但这样做我无法正确地滚动它。我的代码如下:

public class RabinKarp {
private static final int base = 26;
private static final int mod = 1180637;

public static void main(String[] args) {
    String text = "ATCAAGTTACCAATA";
    String pattern = "ATA";
    char[] textArr = text.toCharArray();
    char[] patternArr = pattern.toCharArray();
    System.out.println(getMatchingIndex(textArr, patternArr));
}

public static int getMatchingIndex(char[] textArr, char[] patternArr) {
    int n = textArr.length;
    int m = patternArr.length;
    int patternHash = getHashForPatternSize(patternArr, m);
    int textHash = getHashForPatternSize(textArr, m);
    for(int i = 0; i < n-m; i++) {
        if(patternHash == textHash && checkMatch(textArr, patternArr, i, m))
            return i;
        textHash = rollingHash(textArr, textHash, i, m);    
    }
    return -1;
}

public static boolean checkMatch(char[] textArr, char[] patternArr, int i, int m) {
    for(int j = 0; j < m; j++,i++) {
        if(textArr[i] != patternArr[j])
            return false;
    }
    return true;
}

public static int rollingHash(char[] textArr, int textHash, int i, int m) {
    return (textHash * base - modularExponentiation(base, m, mod) * (int)textArr[i] + (int) textArr[i+m])%mod;
}

public static int getHashForPatternSize(char[] arr, int m) {
    int hash = 0;
    for(int i = 0, p = m; i < m; i++, p--) {
        hash = (hash%mod + calcHash(arr[i], p)%mod)%mod;
    }
    return hash;
}

public static int calcHash(char alphabet, int p) {
    return (((int) alphabet)%mod * modularExponentiation(base, p, mod)%mod)%mod;
}

public static int modularExponentiation(int base, int p, int mod) {
    if(p == 0)
        return 1;
    if(p%2 == 0)
        return modularExponentiation((base*base)%mod, p/2, mod);
    else
        return (base*modularExponentiation((base*base)%mod, (p-1)/2, mod))%mod;
}
}
公共类RabinKarp{
专用静态最终整数基数=26;
专用静态最终整数模=1180637;
公共静态void main(字符串[]args){
字符串text=“atcaagttacata”;
字符串模式=“ATA”;
char[]textArr=text.toCharArray();
char[]patternArr=pattern.toCharArray();
System.out.println(getMatchingIndex(textArr,patternArr));
}
公共静态int getMatchingIndex(char[]textArr,char[]patternArr){
int n=textArr.length;
int m=图案长度;
int patternHash=getHashForPatternSize(patternArr,m);
int textHash=getHashForPatternSize(textArr,m);
对于(int i=0;i

问题是
textHash
patternHash
在任何点上都不匹配。我确信问题在于国防部的运作。有人能告诉我们如何使用mod以及如何正确使用滚动哈希吗。我将非常感激。

< P>计算Rabin Karp滚动哈希的常用方法是考虑大圆序中的字符,而不是您的小Endiad解决方案。这使得算法更加容易,因为它避免了除法。模块划分非常重要,您不能简单地将其实现为
(p/q)%b

如果我们把滚动哈希作为

H0…k-1 = (c0*ak-1 + c1*ak-2 + c2*ak-3 …+… ck-1*a0) mod b
H0…k-1=(c0*ak-1+c1*ak-2+c2*ak-3…+…ck-1*a0)模块b
那么下一个术语是:

H1…k   = (         c1*ak-1 + c2*ak-2 …+… ck-1*a1 + ck*a0) mod b
H1…k=(c1*ak-1+c2*ak-2…+…ck-1*a1+ck*a0)模块b
我们可以很容易地看到这一点

H1…k   = (a * H0…k-1 - c0*ak + ck) mod b
H1…k=(a*H0…k-1-c0*ak+ck)模式b
如果我们随后预计算
m==ak mod b
,则会变成:

H1…k   = (a * H0…k-1 - m * c0 + ck) mod b
H1…k=(a*H0…k-1-m*c0+ck)模式b

每次迭代的工作量要小得多,而且根本不依赖于除法。

您可能需要调试方法
moduleexponention
,但我认为您不需要递归地进行调试。你可以通过迭代来减少复杂性。这个方法是正确的,但问题是,求幂有一定的效果,当我尝试滚动它时(textHash-calcHash(textArr[i],0))/base-这种按基除法不起作用,我想……我的目标是使这个算法适用于更大的值。我当然可以选择基数为10,也可以选择不使用mod,但这不符合我的目的我不知道您使用的是什么语言,但在大多数C语言中,
%
运算符不能正确计算mod,除非两个操作数都是正数。没问题,现在都排序了@rici最初我实现了big-endian解决方案。失败了,然后我选择了小endian。我会认真地做你的,我试过你的方程式,但又失败了。我将更新问题中的代码,但老实说,你的方程只是用不同的方式来表示同一事物。@JotWaraich:不,它们不是。除法在模运算中不起作用。@user2628641:因为模运算符是幂等的,并且分布在加法和乘法上。第一种意思是
(x mod b)mod b
x mod b
完全相同,第二种意思是当您进行加法和乘法时,如果您愿意,您可以应用额外的
mod
,这通常是为了避免整数溢出。@Backrub32:yes