判断str1是否含有str2,如果存在,返回第一次出现的位置,如果不存在,返回-1
str1 = "BBC ABCDAB ABCDABCDABDE";
str2 = "ABCDABD";
(1)思路步骤:
(1)先得到子串的部分匹配表
(2)根据部分匹配表(移动位数=已匹配字符数-对应的部分匹配值)完成匹配
(2)字符串的前缀 后缀的了解
例如:
“bread” 前缀:b br bre bred 后缀:read ead ad d
“a” 前缀后缀都为空
“aa” 前缀 a 后缀 a
字符串的前缀与后缀的最长的共同子串的长度,即为部分匹配表的值
A B C D A B D (例如这里的第二个B指的是"AB" ,这里的第二个A指的是"ABCDA")
0 0 0 0 1 2 0
(3)kmp算法与暴力匹配的比较与解析
例如本例str1与str2进行匹配
- 暴力匹配:在最开始,str2的A并不能与str1进行匹配上,那么在就一直匹配,直到str1的第一个A,这时进行匹配,一直到最后一个str2的D,这时对应的str1为空,不能匹配上,根据传统的暴力匹配,则有str2重新从第二个字符B开始继续与str1进行匹配,这样其实在前面已经有匹配成功的字母,性能低
- kmp算法 :在最后一个str2的D,这时对应的str1为空,不能匹配的时候,str2是从第四个字母后重新开始匹配的,效率高,这里的4 就是根据前面的公式计算而来
代码实现
package com.yues.work;
public class aaa {
public static void main(String[] args) {
String str1="BBC ABCDAB ABCDABCDABDE";
String str2="ABCDABD";
int next[]= kmpNext("ABCDABD");
int kmpsearch = kmpsearch(str1, str2, next);
System.out.println(kmpsearch);
}
private static int[] kmpNext(String dest) {
int next[] =new int[dest.length()];
next[0]=0;
for (int i = 1,j=0; i < dest.length(); i++) {
//核心代码
while (j>0&& dest.charAt(i)!=dest.charAt(j)){
j=next[j-1];
}
if(dest.charAt(i)==dest.charAt(j)){
j++;
}
next[i]=j;
}
return next;
}
public static int kmpsearch(String str1,String str2,int[] next){
for (int i = 0,j=0; i < str1.length(); i++) {
while(j>0&&str1.charAt(i)!=str2.charAt(j)){
j=next[j-1];
}
if(str1.charAt(i)==str2.charAt(j)){
j++;
}
if(j==str2.length()){
return i-j+1;
}
}
return -1;
}
}