暴力匹配
大量的回溯极其影响效率
package datastructure.kmp;
/*
@CreateTime 2021/9/23 17:17
@CreateBy cfk
字符串暴力匹配法
*/
public class ViolenceMatch {
public static void main(String[] args) {
int i = violenceMatch("nhadsf sladfjcfk a", "cfk");
System.out.println(i);
}
public static int violenceMatch(String s1, String s2) {
//分别把两个字符串都转为字符数组方便后面匹配字符
char[] str1 = s1.toCharArray();
char[] str2 = s2.toCharArray();
//定义两个变量作为数组的指针记录
int i = 0;
int j = 0;
//当两个数组没有遍历完时,一直遍历
while (i < str1.length && j < str2.length) {
if (str1[i] == str2[j]) {
i++;
j++;
}else {
i = i - (j - 1);
j = 0;
}
}
//判断是否有找到对应字符串
if (j == str2.length) {
return i-j;
}else {
return -1;
}
}
}
kmp算法
核心是计算出字串的匹配表
package datastructure.kmp;
/*
@CreateTime 2021/9/23 21:36
@CreateBy cfk
KMP算法
*/
import java.util.Arrays;
public class KMPMatch {
public static void main(String[] args) {
String s1 = "BBC ABCDAB ABCDABCDABDE";
String s2 = "ABCDABD";
int[] next = kmpNext(s2);
System.out.println(Arrays.toString(next));
System.out.println(kmpMatch(s1, s2, next));
}
//kmp算法实现
public static int kmpMatch(String s1, String s2, int[] next) {
for (int i = 0,j = 0; i < s1.length(); i++) {
//不相等时,i不动,j继续往前 在比较 找到最大长度的匹配值
//移动的长度和匹配表有关
while (j > 0 && s1.charAt(i) != s2.charAt(j)) {
j = next[j-1]; //比较难理解 算法的核心
}
//如果相等
if (s1.charAt(i) == s2.charAt(j)) {
j++;
}
//当j的长度与字符串2的长度相等时,说明已经找到了
if (j == s2.length()) {
return i-j+1;
}
}
return -1;
}
//获取子串的匹配值表
public static int[] kmpNext(String str){
//创建一个和字串等长的数组
int[] next = new int[str.length()];
//把数组的第一位置为0,因为当数组只有一个数时匹配的为0
next[0] = 0;
for (int i = 1, j = 0; i < str.length(); i++) {
//当遇到不相等的元素 并且前面有相等的元素(因为此时j的值不为0)
//让指针回到前面遇到的第一个不相同的元素 比如 ABCDABD 在判断最后一位时直接应该把指针放在B上面
// 0000120 即next[j-1]对应1
while (j > 0 && str.charAt(i) != str.charAt(j)) {
j = next[j-1]; //比较难理解 算法的核心
}
//当遇到两个元素相等的时候 让记录匹配值加一,如果第二位也相等则再加一 以此类推 最后把值赋给当前位置字符
if (str.charAt(i) == str.charAt(j)){
j++;
}
next[i] = j;
}
return next;
}
}