懒了这么久,重新开始吧。
今天再来看看kmp算法。
题目
实现 strStr() 函数。
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。
示例 1:
输入: haystack = "hello", needle = "ll" 输出: 2
示例 2:
输入: haystack = "aaaaa", needle = "bba" 输出: -1
说明:
当 needle
是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。
对于本题而言,当 needle
是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。
分析
其实这道题用java里面haystack.indexOf(needle),一下就可以出来,但是自己kmp总是迷迷糊糊,打算再写一遍。
next函数很重要,求出needle字符串的最大相同的前缀后缀长度,这个长度决定着在haystack和needle比较时遇到不同字母需要偏移多少长度。注意在不满足相同的前缀后缀字母时,k值需要回溯,回溯到上一个最大相同前缀后缀,直到字母相同或者k=-1。
kmp算法让needle与haystack比较,当比较到不同字母时,不一定要重新从头再开始比较,这时候要偏移的位置长度就和next数组中的数有关了。
今天先粗略的记一下,周六日了之后要再详细的回顾一下。
代码
class Solution {
public int strStr(String haystack, String needle) {
if((needle.length() == 0 && haystack.length() == 0) || needle.length()==0) return 0;
int[] next = new int[needle.length()];
next(needle,next);
int k = -1;
for (int i = 0; i < haystack.length(); i++) {
while( k > -1 && needle.charAt(k+1) != haystack.charAt(i) )
k = next[k];
if (needle.charAt(k+1) == haystack.charAt(i))
k ++;
if (k == needle.length()-1) return i - k ;
}
return -1;
}
public static void next(String needle, int[] next){
char[] chars = needle.toCharArray();
next[0] = -1;
int k = -1;
for (int i = 1; i < next.length; i++) {
while( k != -1 && chars[i] != chars[k+1])
k = next[k];
if ( chars[i] == chars[k+1]) k = k+1;
next[i] = k;
}
}
}