KMP算法的核心是求解next数组。
首先要理解next数组的含义。
next[i]包含s[i]之前的子串(即s[0…i-1],不包含s[i])最长公共前后缀的信息。其值表示公共前后缀前缀的最后一位下标。
next数组的作用是指示模式串pattern失配后应该退回的位置,因此在做题的时候,要根据字符串的下标是从0开始还是从1开始来判断整体是否要加上1。
next数组可以优化为nexval数组,进一步减小时间复杂度。
nextval数组表示pattern失配时的最佳回退位置。
求解next的核心:
s[i]==s[next[j]+1]? next[i] = next[j] + 1 : next[i] = j (循环本句);
求解next数组
// getNext求解长度为len的字符串s的next数组
void getNext(char s[],int len)
{
int j = -1;
next[0] = -1;//初始化j=next[0] = -1
for(int i = 1;i < len;i++)//求解next[1] ~ next[len - 1]
{
while(j != -1 && s[i] != s[j+1])
{
j = next[j];//反复令j = next[j]
}
if(s[i] == s[j + 1])//如果s[i] == s[j+1]
{
j++;//则next[i] = j + 1,先令j指向这个位置
}
next[i] = j;//令next[i] = j
}
}
判断是否是子串
//KMP算法,判断pattern是否是text的子串
bool KMP(char text[],char pattern[])
{
int n = strlen(text),m = strlen(pattern);//字符串长度
getNext(pattern,m);//计算pattern的next数组
int j = -1;//初始化j为-1,表示当前还没有任意一位被匹配
for(int i = 0;i < n; i++)//试图匹配text[i]
{
while(j != -1 && text[i] != pattern[j+1])
{
j = next[j];//不断回退,直到j回到-1或text[i] = pattern[j + 1]
}
if(text[i] == pattern[j + 1])
{
j++;//text[i] 与pattern[j+1] 匹配成功,令j加1
}
if(j == m -1)//pattern完全匹配,说明pattern是text的子串
{
return true;
}
}
return false; //执行完text还没匹配成功,说明pattern不是text的子串
}
统计pattern出现次数
//KMP算法,统计pattern在text中出现的次数
int KMP(char text[],char pattern[])
{
int n = strlen(text),m = strlen(pattern);
getNext(pattern,m);
int ans = 0,j = -1;
for(int i = 0 ; i <n ; i++)
{
while(j != -1 && text[i] != pattern[j+1])
{
j = next[j];
}
if(text[i] == pattern[j + 1])
{
j++;
}
if(j == m - 1)
{
ans++;
j = next[j];
}
}
return ans;
}
求解nextval数组
// getNextval求解长度为len的字符串s的nextval数组
void getNextval(char s[],int len)
{
int j = -1;
nextval[0] = -1;//初始化j=next[0] = -1
for(int i = 1;i < len;i++)//求解next[1] ~ next[len - 1]
{
while(j != -1 && s[i] != s[j+1])
{
j = nextval[j];//反复令j = next[j]
}
if(s[i] == s[j + 1])//如果s[i] == s[j+1]
{
j++;//则next[i] = j + 1,先令j指向这个位置
}
//与getNext数组相比只有此处不同
if(j == -1 || s[i+1] != s[j+1])
{
nextval[i] = j;
}
else
{
nextval[i] = nextval[j];
}
}
}
有限状态状态自动机,KMP从初始到终止的状态转移。
扩展:AC自动机(非严肃解释,仅用来帮助理解KMP算法)
通常把解决多维字符串匹配(一个文本串匹配多个字符串)的算法称为AC自动机