暴力匹配
最经典的方法,其实效率也没那么差,时间复杂度O(n + k),此处我列举极端情况,就是每次匹配都匹配到最后一位,代码如下:
public class ViolenceMatch {
public int violenceMatch(String str1, String str2) {
char[] c1 = str1.toCharArray();
char[] c2 = str2.toCharArray();
int i = 0;
int j = 0;
while (i < c1.length && j < c2.length)
if (c1[i] == c2[j]){//匹配字符,当完全匹配str2的时候,此时由于j = c2.length,while就会退出
i++;
j++;
}else {
i = i - j + 1;
j = 0;
}
if (j == c2.length)
return i - j;
else return -1;
}
}
KMP匹配字符串
原理我都写在注释上了,代码如下:
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;
}
public static int[] kmpNext(String dest) {//得到的是一个数组,保存部分匹配值
int[] next = new int[dest.length()];//创建该数组
next[0] = 0;//无论哪一个字符串,其第一个字符的部分匹配值都是0
for (int i = 1, j = 0; i < dest.length(); i++) {//由于第一个字符的部分匹配值是0,因此可以从第二个字符开始遍历;j是作为第一个字符的指针
while (j > 0 && dest.charAt(i) != dest.charAt(j))
j = next[j - 1];//当遇到不匹配的,先控制不越界,由于此时charAt[j]已经比较过了,即与charAt[i]比较过了,可以向前进一位,即优化了,不优化的话写成j = 0;也是可以的
if (dest.charAt(i) == dest.charAt(j)) j++;//当遇到匹配的字符时,指向第一个字符的指针向后移一位,即j++;
next[i] = j;//并令在遍历dest的指针等于j
}
return next;
}
匹配首字符匹配法
主要容易理解,而且容易写,代码如下:
public static int violenceMatch(String dest, String target) {
char[] destArr = dest.toCharArray();
char[] targetArr = target.toCharArray();
int targetLen = targetArr.length;
int i = 0, j = 0;
while (i < destArr.length && j < targetLen)
if (destArr[i] == targetArr[j]) {
i++;
j++;
} else {
i = getSameIndex(destArr,targetArr,i,j);
j = 0;
}
if (j == targetLen)
return i - j;
else return -1;
}
public static int getSameIndex(char[] destArr, char[] targetArr, int i, int j) {//将匹配短数组第一个字符在长数组中的位置输出
for (int k = i - j + 1; k <= i; k++)
if (targetArr[0] == destArr[k])
return k;
return i - j + 1;
}