28. Find the Index of the First Occurrence in a String
KMP
- 目的
- 用来快速查找字符串A(文本串)中是否存在字符串B(模式串),即
- 为什么快
- TC M+N线性速度,传统两个循环需要 M*N
- 结构
- next数组
- 整个过程其实有点像DP, 用已知求未知
-
java private void getNext(int[] next, String s){ int j = 0; next[0] = 0;//初始化 for(int i = 1; i< s.length(); i++){ while(j > 0 && s.charAt(j) != s.charAt(i)){ j = next[j - 1]; // 不相等回退到next[j-1]的位置 } if ( s.charAt(j) == s.charAt(i)){ j++; // 相等则j++,(最长字串长度+1) } next[i] = j; // next[i] 赋值 } }
- 匹配过程
- 跟求next数组有点类似
-
java class Solution { public int strStr(String haystack, String needle) { int[] next = new int[needle.length()]; 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++; // 如果匹配上 j++ } if ( j == needle.length()){ //此时由于上面的j++, j值刚好等于其index return i - j + 1; //这里理解成求首项index, i - index + 1 = len = j ——> index = i - len(j) + 1; } } return -1;
- next数组
459. Repeated Substring Pattern
- 思路
- KMP方法
- 求最小重复子串长度 len = s. length() - next[s.length() - 1];
- 再看这个子串
- 是否等于原长度
- 等于 return false,这个说明next[s.length() - 1] = 0 得从头比,说明没有重复的前后缀(子串), 也就是说这个字符串内压根就没重复的形式
- 不等于原长
- 看看 len是否能整除 s.length(),照道理,如果true的话,总长度是重复长度的n倍,能整除
- 是否等于原长度
-
java class Solution { public boolean repeatedSubstringPattern(String s) { int[] next = new int[s.length()]; getNext(next, s); int len = s.length() - next[s.length() - 1]; //求最小重复子串 if (len == s.length()){ return false;//这种情况就是没有重复的前后缀 } return s.length() % len == 0 ? true : false; //看看 len是否能整除 s.length(),照道理,如果true的话,总长度是重复长度的n倍,能整除 } private void getNext(int[] next, String s){ //next 数组 int j = 0; next[0] = 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(i) == s.charAt(j)){ j++; } next[i] = j; } } }
- 移动匹配
- s+s
- 去掉头尾的字符
- 如果含有s就是true
-
java class Solution { public boolean repeatedSubstringPattern(String s) { String doubleS = s + s; String newS = doubleS.substring(1, doubleS.length() - 1); return newS.contains(s); // 下面是用KMP求的contains() // int[] next = new int[s.length()]; // getNext(next, s); // int j = 0; // for(int i = 0; i < newS.length(); i++){ // while(j > 0 && newS.charAt(i) != s.charAt(j)){ // j = next[j - 1]; // } // if ( newS.charAt(i) == s.charAt(j)){ // j++; // } // if( j == s.length()){ // return true; // } // } // return false; } 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; } }
- s+s