LeetCode第28题-KMP算法-找出字符串中第一个匹配项的下标-java实现-图解思路与手撕代码
一、题目描述
给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。
二、解题思路与代码实现
1.解题思路
经典字符串匹配问题,这里着重讲解KMPnext数组的求解。
举个例子,对于给定的字符串p(a,a,a,b,b,a,b),要求得KMPnext数组n(0,1,2,0,0,1,0)。
首先初始化i=1,j=0,和数组n(0,0,0,0,0,0,0)。
分别移动下标i和j,当p(i)=p(j)时,令n(i)=j+1,i++,j++。
当p(i)!=p(j)时,令j=n(j-1),并循环判断p(i)和p(j)是否相等,直到p(i)=p(j) 或 j=0,若p(i)=p(j),令n(i)=j+1,i++,j++。若j==0,令n(i)=0,i++。
2.代码实现
主函数代码:
private static int strStr(String haystack, String needle) {
int[] kmpArr = kmpNext(needle);
char[] hayCh = haystack.toCharArray();
char[] needCh = needle.toCharArray();
int i = 0, j = 0, idx = -1;
while (i < hayCh.length & j < needCh.length) {
if (hayCh[i] == needCh[j]) {
i++;
j++;
if (j == needCh.length) {
return i - j;
}
} else {
if (j >= 1) {
j = kmpArr[j - 1];
} else {
i++;
}
}
}
return -1;
}
KMPnext数组计算代码:
private static int[] kmpNext(String str) {
int[] kmpArr = new int[str.length()];
kmpArr[0] = 0;
int i = 1, j = 0;
while (i < kmpArr.length) {
if (str.charAt(i) == str.charAt(j)) {
kmpArr[i] = j + 1;
i++;
j++;
} else {
while (str.charAt(i) != str.charAt(j)) {
if (j - 1 >= 0) {
j = kmpArr[j - 1];
if ((str.charAt(i) != str.charAt(j))) {
break;
}
} else {
kmpArr[i] = 0;
i++;
break;
}
}
}
}
return kmpArr;
}
总结
对于经典KMP算法,KMPnext数组的求取是关键。