28.找出字符串中第一个匹配项的下标
本题是KMP算法的经典应用,求解分为两个部分,一个是求字串的
next
数组,另一个是用KMP算法匹配主串和字串,求next
数组时,用next[j]
来求next[j+1]
,初值为next[0]=-1
,next[1]=0
void buildNext(string needle,int next[],int m){
int k=next[0]=-1;
//用next[j]求next[j+1]
for (int j = 0; j < m-1; ++j) {//j+1<m
k=next[j];
while (k>=0&&needle[k]!=needle[j]){
k=next[k];
}
next[j+1]=++k;
}
}
模式匹配的思路是,若在
j
处失配,则主串指针i
不动,令字串的指针j=next[j]
,继续进行匹配,若最后匹配完成时j==m
也就是j
指向了字串的最后一位的后一位代表着字串匹配成功,否则失败
特殊情况是j==0
处失配,此时应将i
后移一位,所以才将next[0]
赋值为-1
int strStr(string haystack, string needle) {
int n=haystack.size();
int m = needle.size();
int next[10005];
buildNext(needle, next, m);
int i = 0;
int j = 0;
while (j<m&&i<n){
if (j == -1 || haystack[i] == needle[j]) {
i++;
j++;
} else{
j=next[j];
}
}
return (j==m)?i-m:-1;
}
459.重复的子字符串
由数学推导可知,一个字符串的长度
len
,其最长相等前后缀的长度为next[len]
,若len%(len-next[len]))==0
,则可由前len-next[len]
个字符重复组成,否则无法重复组成
class Solution {
public:
void buildNext(int next[],string &s){
next[0]=-1;
next[1]=0;
//用next[j]算next[j+1]
int k;
for(int j=0;j<=s.size()-1;j++){//j+1<=size
k=next[j];
while (k>=0&&s[j]!=s[k]){
k=next[k];
}
next[j+1]=k+1;
}
return;
}
bool repeatedSubstringPattern(string s) {
int next[s.size()+1];
buildNext(next,s);
int len=s.size();
if(next[len]!=0&&(len%(len-next[len]))==0){
return true;
}
return false;
}
};