Java KMP算法,can';我不明白
我很难理解KMP算法。我了解什么是前缀后缀,我编写了代码来计算前缀后缀表: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
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算法
既然我们已经找到了与文本匹配的模式的子字符串,它不是更好吗