Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/341.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
Java KMP算法,can';我不明白_Java_Algorithm - Fatal编程技术网

Java KMP算法,can';我不明白

Java KMP算法,can';我不明白,java,algorithm,Java,Algorithm,我很难理解KMP算法。我了解什么是前缀后缀,我编写了代码来计算前缀后缀表: private int[] calculatePrefSuffArray(String pattern) { char patternArray[] = pattern.toCharArray(); int tab[] = new int[pattern.length()]; tab[0] = 0; int t = tab[0]; for (int i = 1; i < p

我很难理解KMP算法。我了解什么是前缀后缀,我编写了代码来计算前缀后缀表:

 private int[] calculatePrefSuffArray(String pattern) {
    char patternArray[] = pattern.toCharArray();
    int tab[] = new int[pattern.length()];
    tab[0] = 0;
    int t = tab[0];
    for (int i = 1; i < pattern.length(); i++) { // t = tab[i-1]
        while(t >0 && patternArray[i] != patternArray[t] ) {
            t = tab[t-1];
        }
        if(patternArray[i] == patternArray[t]) t++;
        tab[i] = t;
    }
    return tab;
}
private int[]计算引用数组(字符串模式){
char patternArray[]=pattern.toCharArray();
int tab[]=新int[pattern.length()];
制表符[0]=0;
int t=制表符[0];
对于(inti=1;i0&&patternArray[i]!=patternArray[t]){
t=选项卡[t-1];
}
if(patternArray[i]==patternArray[t])t++;
表[i]=t;
}
返回选项卡;
}

但我不明白如何在KMP中使用它。有人能给我解释一下吗?

你的
计算引用数组(“ABC-ABCDAB-abcdcdabde”)
会返回这个

[0  0  0  0  1  2  3  0  1  2  0  1  2  3  0  1  2  3  0  1  2  0  0]
而不是这个

[-1  0  0  0  1  2  3  0  1  2  0  1  2  3  0  1  2  3  0  1  2  0  0 ]
通过替换以下内容来更正代码

tab[0] = 0;
int t = tab[0];
用这个

tab[0] = -1;
tab[1] = 0;
int t = tab[1];
传递从
calculatePrefSuffArray(字符串模式)
函数返回的创建的
int[]表。
如果在
string
文本中找到
word
,它将返回
true

private boolean search(String string, String word, int[] table) {
    int m = 0, i = 0;
    while ((m + i) < string.length()) {
        if (word.charAt(i) == string.charAt(m + i)) {
            if (i == word.length() - 1) {
                return true;
            }
            i++;
        } else {
            if (table[i] > -1) {
                m = m + i - table[i];
                i = table[i];
            } else {
                i = 0;
                m++;
            }
        }
    }
    return false;
}
私有布尔搜索(字符串、字符串字、int[]表){
int m=0,i=0;
而((m+i)-1){
m=m+i-表[i];
i=表[i];
}否则{
i=0;
m++;
}
}
}
返回false;
}

如果您在理解代码方面有任何问题,请告诉我。

您的
calculatePrefSuffArray(“ABC ABCDAB ABCDABCDABDE”)
将返回此信息

[0  0  0  0  1  2  3  0  1  2  0  1  2  3  0  1  2  3  0  1  2  0  0]
而不是这个

[-1  0  0  0  1  2  3  0  1  2  0  1  2  3  0  1  2  3  0  1  2  0  0 ]
通过替换以下内容来更正代码

tab[0] = 0;
int t = tab[0];
用这个

tab[0] = -1;
tab[1] = 0;
int t = tab[1];
传递从
calculatePrefSuffArray(字符串模式)
函数返回的创建的
int[]表。
如果在
string
文本中找到
word
,它将返回
true

private boolean search(String string, String word, int[] table) {
    int m = 0, i = 0;
    while ((m + i) < string.length()) {
        if (word.charAt(i) == string.charAt(m + i)) {
            if (i == word.length() - 1) {
                return true;
            }
            i++;
        } else {
            if (table[i] > -1) {
                m = m + i - table[i];
                i = table[i];
            } else {
                i = 0;
                m++;
            }
        }
    }
    return false;
}
私有布尔搜索(字符串、字符串字、int[]表){
int m=0,i=0;
而((m+i)-1){
m=m+i-表[i];
i=表[i];
}否则{
i=0;
m++;
}
}
}
返回false;
}

如果您在理解代码方面有任何问题,请告诉我。

朴素算法

在普通模式匹配算法中,如果您有一个长度为 m和长度为n的文本,将匹配模式的m个字符 通常针对文本的n个字符,但如果已经出现不匹配,您可以使用退出函数来避免某些匹配,从而稍微避免这种行为。

因此,该算法的渐近复杂度为O(mn)

但是朴素算法的问题在于它不试图理解任何关于模式的东西。例如,如果你在一家公司工作了5年,你可以利用这5年的工作经验来获得某种好处。类似地,我们可以分析子字符串并推断出一些关于这一点的有用信息。这正是计算前缀函数时要做的。

KMP算法


既然我们已经找到了与文本匹配的模式的子字符串,那么将模式向右滑动6次(找到子字符串匹配的位置)-1次(位置6的前缀函数)并立即重新开始比较不是更好吗?事实上,前缀函数值用于确定模式必须向右滑动的次数。最初可能有点难以理解,但请拿一张纸,将一个小文本与一个小模式进行比较,写下所有变量的中间值,然后您将欣赏该算法的美妙。

该算法的渐近复杂度为O(m+n),因为我们正在滑动过去 每次出现不匹配时的模式。

<强>算法的C++实现如下:< /强> BR> 程序1:创建大小为10000000的图案,并将其存储在文件inputtext.txt中(您可以更改大小。也许!)

#包括
#包括
#包括
使用名称空间std;
main()
{
流myfile(“inputtext.txt”);
char*intxt=“abcd”;//我希望示例文本只包含这些字母
长整数i=0;
char*txt=新字符[10000000];

而(i朴素算法

在普通模式匹配算法中,如果您有一个长度为 m和长度为n的文本,将匹配模式的m个字符 通常针对文本的n个字符,但如果已经出现不匹配,您可以使用退出函数来避免某些匹配,从而稍微避免这种行为。

因此,该算法的渐近复杂度为O(mn)。

但naive算法的问题在于,它不试图了解模式的任何内容。例如,如果你在一家公司工作了5年,你可以利用这5年的经验在某种程度上为你带来好处。同样,我们可以分析子字符串并推断出一些关于这方面的有用信息。这正是你的本来面目计算前缀函数时执行此操作。

KMP算法


既然我们已经找到了与文本匹配的模式的子字符串,它不是更好吗