代码随想录算法训练营Day9|字符串part02
一、28. 找出字符串中第一个匹配项的下标(KMP)
难点在于求前缀数组
class Solution {
public int strStr(String haystack, String needle) {
int H=haystack.length();//总串
char[] h=new char[H+1];
for(int i=1;i<=H;i++){
h[i]=haystack.charAt(i-1);
}
int N=needle.length();//模式串
if (N == 0) {
return 0;
}
char[] n=new char[N+1];
for(int i=1;i<=N;i++){
n[i]=needle.charAt(i-1);
}
//构造前缀数组
int next[]=new int[N+1];
// int k=0;
for(int i=2,j=0;i<=N;i++){
//从第二个开始配对
while(j!=0&&n[i]!=n[j+1]){
j=next[j];}
if(n[i]==n[j+1]){
j++;
}
next[i]=j;
// k=j;
}
// System.out.println("最大前缀是"+k);
//KMP
for(int i=1,j=0;i<=H;i++){
while(j!=0&&h[i]!=n[j+1]){
j=next[j];
}
if(h[i]==n[j+1]){
j++;
}
if(j==N){
int q;
q= i - N ;
j = next[j]; // 完全匹配后继续搜索
return q;
}
}
return -1;
}
}
二、459.重复的子字符串(KMP)
数组长度减去最长相同前后缀的长度相当于是第一个周期的长度,也就是一个周期的长度,如果这个周期可以被整除,就说明整个数组就是这个周期的循环。
class Solution {
public boolean repeatedSubstringPattern(String s) {
if(s.equals(""))return false;
int len=s.length();
char[] S=new char[len+1];
for(int i=1;i<=len;i++){
S[i]=s.charAt(i-1);
}
//构造next[]数组
int next[]=new int[len+1];
for(int i=2,j=0;i<=len;i++){
//匹配不成功,j向前退
while(j!=0&&S[i]!=S[j+1]){
j=next[j];
}
//匹配成功,j向后进
if(S[i]==S[j+1]){
j++;
}
//更新next数组的值
next[i]=j;
}
//KMP判断
if(next[len]>0 && len % (len - next[len]) == 0){
return true;
}
return false;
}
}