/**
* 对于非空串T,计算它的next数组
**/
void get_next(const char* T, int* next)
{
//输入检查
if(T == NULL || *T == '\0' || next == NULL) return;
int i = 1, j = 0;
next[0] = 0;
int lenT = strlen(T);
while(i < lenT)
{
if(j == 0 || T[i-1] == T[j-1])
{
i++;
j++;
next[i-1] = j;
}
else j = next[j-1];
}
}
/**
* 主串是S(被匹配),子串是T(匹配),假设从主串的pos位置开始匹配;
* 如果匹配成功,则返回主串中第一次与子串匹配的那部分的开始位置;
* 否则,返回-1;
* 复杂度为O(lenS+lenT)
**/
int KMP(const char* S, const char* T, int pos)
{
//输入检查
if(S == NULL || T == NULL || *S == '\0' || *T == '\0') return -1;
//分析子串,得到子串的next数组
int lenT = strlen(T); //O(lenT)
int *next = new int[lenT];
get_next(T,next); //O(lenT)
int i = pos + 1;
int j = 1;
int lenS = strlen(S); //O(lenS)
//开始模式匹配
while(i <= lenS && j <= lenT) //O(lenS)
{
if(j == 0 || S[i-1] == T[j-1])
{
i++;
j++;
}
else j = next[j-1];
}
if(j > lenT) return i - lenT - 1;
else return -1;
}