目录
找出字符串中第一个匹配项的下标
-
什么是KMP
-
它是三位学者名字的首字母
-
-
KMP有什么用
-
我现在觉得就是查找匹配值的时候可以用
-
文章说的是当出现字符串不匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头再去做匹配了。
-
-
什么是前缀表
-
记录了最长相同前后缀的数组
-
文章说的是KMP里面的next数组就是一个前缀表(prefix table),记录下标i之前(包括i)的字符串中,有多大长度的相同前缀后缀。。
-
-
为什么一定要用前缀表
-
前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配的时候,模式串应该从哪里开始重新匹配。
-
-
如何计算前缀表
-
搞清楚前缀和后缀什么意思?
-
前缀就是去尾巴字母的连续字符串
-
后缀就是去脑袋字母的连续字符串
-
-
计算方式
-
比如 'a' 去头计算和去尾计算,都是啥也不剩,所以最长相同前后缀长度:0
-
比如 'aa' 去头计算和去尾计算,都是只留下一个字母a,所以最长相同前后缀长度:1
-
比如 'aab' 去头计算和去尾计算,前缀aa && 后缀ab,这里一开始a b都不相同 所以最长相同前后缀长度:0
-
比如 'aaba' 去头计算和去尾计算,前缀aab && 后缀aba,相同的只有前者的首和后者的尾的字母a,所以最长相同前后缀长度:1
-
比如 'aabaa' 去头计算和去尾计算,同理可得,最长相同前后缀长度:2
-
-
-
前缀表与next数组
-
这个数组就用来存放最长相同前后缀的长度
-
正解:
class Solution { public void getNext(int[] next,String s){ //创建next数组 以及如何为数组添加元素 int j=-1;//初始化,这个j代表前缀,j初始值-1 next[0]=j;//这里不用管第一个字母,因为最长相同前后缀等于0 for(int i=1;i<s.length();i++){ //i代表后缀,初始化完成 //回退操作写在循环里面,而不是if语句里面, //因为j走到后面,不能只回退一次嘛,它必须在回退的过程中逐一比较,求出最长相同前后缀的值 while(j>=0 && s.charAt(i) != s.charAt(j+1)){ j=next[j]; } if(s.charAt(i) == s.charAt(j+1)){ j++; } next[i]=j; //相同时,记录j的值到next数组中,然后j i向前移动 } } public int strStr(String haystack, String needle) { int[] next=new int[needle.length()]; getNext(next,needle); int j=-1; //i作为下标使用在haystack //j作为下标使用在needle for(int i=0;i<haystack.length();i++){ while(j>=0 && haystack.charAt(i)!=needle.charAt(j+1)){ j=next[j]; } if(haystack.charAt(i)==needle.charAt(j+1)){ j++; } if(j == needle.length()-1) {return i-needle.length()+1;} } return -1; } }