对问题:在主串中找到子串,若找到,则返回子串首在主串中的下标 ,否则返回-1
算法核心思想是,主串中下标 i 不回溯,求得子串的next数组(作用就是,如果到了这个位置不匹配了,那接下来子串下标 j 该回溯到哪里),然后开始对下标为 i 的主串和下标为 j 的子串逐个匹配,遇到不匹配时,找next数组中 next[j]存放的下标,将 j 回溯到此。
PS:其实返回0也可以,因为S[0]、T[0]被用来保存字符串的长度了,真正字符串是从下标1开始的。
#include <bits/stdc++.h>
using namespace std;
void get_next(char T[], int *next)
{
int i = 1, j = 0;
next[1] = 0;
while (i < T[0])//T[0]存放的是该字符串的长度,具体字符从T[1]开始
{
if (j == 0 || T[i] == T[j])//推到next数组
{
i++;
j++;
next[i] = j;
}
else
j = next[j];
}
}
//对next数组进行改进
void get_nextval(char T[], int *next)//对next数组进行改进
{
int i = 1, j = 0;
next[1] = 0;
while (i < T[0])
{
if (j == 0 || T[i] == T[j])
{
i++;
j++;
if (T[i] != T[j])//遇到不同的才继续向前
next[i] = j;
else//遇到相同的则保存与之前相同的
next[i] = next[j];
}
else
j = next[j];
}
}
int Index_KMP(char S[], char T[], int pos)
{
int i = pos;
int j = 1;
int next[255];
get_nextval(T, next);
while (i <= S[0] && j <= T[0])
{
if (j == 0 || S[i] == T[j])
i++, j++;
else
j = next[j];
}
if (j > T[0])
return i - T[0];
else return -1;
}
int main()
{
char S[255], T[255];
strcpy(S + 1, "AAAABCDEF");
S[0] = strlen(S + 1);
strcpy(T + 1, "AB");
T[0] = strlen(T + 1);
printf("%d\n",Index_KMP(S, T, 1));
return 0;
}