找出字符串中第一个匹配项的下标题目如下:

在一个字符串中寻找是否出现过另一个模式串,单用暴力法解决复杂度是很高的,所以出现了经典的KMP算法!!!它的经典思想就是当出现字符串不匹配时,可以记录一部分之前已经匹配的文本内容,利用这些信息避免从头再去做匹配,复杂度可以大大的降低。但它的算法思想需要深刻理解,否则只是背下来的话,过一段时间也会忘不会写。
在学习KMP之前,需要知道前缀表和后缀表,最长相等前后缀的知识:
对于一个字符串,前缀是指除了最后一个字符以外,从第一个字符开始的所有连续子串;后缀是指除了第一个字符以外,到最后一个字符结束的所有连续子串。最长相等前后缀就是前缀和后缀中相同且长度最长的那个子串的长度。
举个具体的例子:
- 前缀有:
"a"、"ab"、"abc"、"abca" - 后缀有:
"bcab"、"cab"、"ab"、"b" - 最长公共前后缀是
"ab",长度为 2。
这个最长公共前后缀会在KMP算法中发挥重要作用,里面有个next数组,实际上他就是一个前缀表,用来回退的,它记录了模式串与文本串不匹配的时候,模式串应该从哪里开始重新匹配。前缀表:记录下标i之前(包括i)的字符串中,有多大长度的相同前缀后缀。
为什么需要这个前缀表呢,我是这样理解的:对模式串中每i个字符之前的字符串中不是已经算出来不匹配的话需要回退到哪里吗,因为一旦后面的字符不匹配,由于有相同的前缀和后缀,舍弃掉前面的前缀,就可以拿后缀(这个后缀与前面的前缀是相同的)当做下一次的前缀(相当于记录之前已经匹配过的)
class Solution {
public int strStr(String haystack, String needle) {
//前缀表不减一实现
if (needle.length() == 0) return 0;
//1.对模式串创建其前缀表
int[] next = new int[needle.length()];
//2.构建函数得到前缀表
getNext(next, needle);
int j = 0;
for(int i = 0; i < haystack.length(); i++){
while(j >0 && needle.charAt(j) != haystack.charAt(i))
j = next[j-1];
if(needle.charAt(j) == haystack.charAt(i))
j++;
if(j == needle.length())
return i - needle.length() +1;
}
return -1;
}
private void getNext(int[] next, String s){
int j =0;
for(int i = 1; i < s.length(); i++){
while(j > 0 && s.charAt(j) != s.charAt(i))
j = next[j-1];
if (s.charAt(j) == s.charAt(i))
j++;
next[i] = j;
}
}
}
1127

被折叠的 条评论
为什么被折叠?



