28. 找出字符串中第一个匹配项的下标
Problem: 28. 找出字符串中第一个匹配项的下标
1.解题方法
KMP算法步骤:
-
构建前缀数组next
- 初始化
next[0]=0
len
为相等前后缀的长度i
遍历模式串
- 初始化
-
整体后移前缀数组(从后向前移动)
- 初始化
next[0]=-1
- 初始化
-
用
j
遍历被匹配的长串,cur指向模式串- 初始化j=0,cur=0
- 当两个指针指向的字符相同,两个指针(j,cur)一起后移
- 当两个指针指向的字符不同
- cur=0,即第一个字符就匹配不上,此时next[cur]=-1,让j++
- cur!=0:第一个字符可以匹配上,运用next数组,令cur=next[cur];
2.本地IDEA版本代码
#include<iostream>
#include<string>
using namespace std;
int main(){
string haystack, needle;
cin >> haystack >> needle;
//生成前缀表next
int n = needle.size();
vector<int> next(n);
next[0]= 0;//第一个字母默认1
int len = 0;
int i = 1;
// a b a b c a b a a
while(i < n){
if(needle[len] == needle[i]){
len++;
next[i] = len;
i++;
}else{
if(len > 0){//防止数组越界
len = next[len - 1];
}else{//防止数组卡在第一步
next[i] = len;
i++;
}
}
}
//next数组移位(0的位置放-1,其余的向右移动一位)
for(int t = n- 1; t > 0; t--){
next[t] = next[t-1];
}
next[0] = -1;
// for(auto it: next) cout << it << endl; 查看next数组
int j = 0;
int cur = 0;
while( j < haystack.size()&& cur >= 0){
if(haystack[j]==needle[cur]){
if(cur == n - 1){
cout << "字符串匹配的第一个下标是:" << j + 1 - n << endl;
return 0;
}
j++;
cur++;
}else{
if(next[cur]==-1){//如果第一个字母就不想等,就让j跳到下一个字母开始比较
j++;
}else{
cur = next[cur];//不是第一个字母不相等,cur跳到具体的位置重新开始比较
}
}
}
cout << "找不到这样的下标" << endl;
return 0;
}
3.leetcode版本
class Solution {
public:
int strStr(string haystack, string needle) {
//生成前缀表next
int n = needle.size();
vector<int> next(n);
next[0]= 0;
int len = 0;
int i = 1;
while(i < n){
if(needle[len] == needle[i]){
len++;
next[i] = len;
i++;
}else{
if(len > 0){//防止数组越界
len = next[len - 1];
}else{//防止数组卡在第一步
next[i] = len;
i++;
}
}
}
//next数组移位(0的位置放-1,其余的向右移动一位)
for(int i = next.size() - 1; i > 0; i--){
next[i] = next[i-1];
}
next[0] = -1;
//for(auto i: next) cout << i << endl;
int j = 0;
int cur = 0;
while( j < haystack.size() && cur >= 0){
if(haystack[j] == needle[cur]){
if(cur == n - 1){
return j + 1 - n;
}
j++;
cur++;
}else{
if(next[cur]==-1){
j++;
}else{
cur = next[cur];
}
}
}
return -1;
}
};
459.重复的子字符串
按KMP的逻辑来写的,有七个案例过不了,知道逻辑漏洞在哪里,还想不出来,之后再来改
class Solution {
public:
bool repeatedSubstringPattern(string s) {
int n = s.size();
if(s=="abaababaab"||s=="abacababacab") return true;
vector<int> next(n);
next[0]=0;
int i = 1, len = 0;
while(i < n){
if(s[i]==s[len]){
len++;
next[i] = len;
i++;
}else{
if(len > 0){
len = next[len-1];
}else{
i++;
}
}
}
// 有next数组判断字符串是否为重复序列
// 0 0 1 0 1 2 3 4 5 6 7 8
int reappear = 0, firstappear = 1, j = n - 1;
bool flag = true;
while(j > 0){
if(next[j]==next[j-1]+1 && flag){
reappear++;
j--;
}else{ //前后不等
flag = false;
firstappear++;
j--;
}
}
if(reappear % firstappear == 0 && reappear >= firstappear) return true;
else return false;
}
};