// 模式串最大长度
const int MAX_P_LEN = 1024;
// next数组,next[i]代表模式串前缀pattern[0-i]的最大公共前后缀
// 同时,next[i]也代表当模式串在第i个位置字符失配时,下一次应该用来与当前位置的文本串字符继续比较的模式串字符位置
int next[MAX_P_LEN];
// 构建模式串pattern的next数组值
void getFail(char pattern[])
{
int PatLen = strlen(pattern);
// 初始化递推边界
next[0] = 0;
next[1] = 0;
// 构建模式串pattern的每一个前缀的next值,即计算其最大公共前后缀的长度
for(int i=1; i<PatLen; ++i)
{
int j = next[i];
// 在前缀中递推搜寻
while(j && pattern[i]!=pattern[j]) j = next[j];
next[i+1] = pattern[i]==pattern[j] ? j+1 : 0;
}
}
// 用于判断文本串text中是否包含模式串pattern
int kmp(char text[], char pattern[])
{
int TextLen = strlen(text);
int PatLen = strlen(pattern);
// 当前比较的模式串字符位置
int j = 0;
// 比较文本串的每一个字符
for(int i=0; i<TextLen; ++i)
{
// 失配时沿着失配边走,直到可以匹配或回到模式串的第一个字符
while(j && text[i]!=pattern[j]) j = next[j];
// 比较当前文本串字符和移动后的模式串当前字符
if (text[i] == pattern[j]) ++j;
// 如果模式串的所有字符都比较相等了,则完成模式匹配
if (j == PatLen) return 1;
}
return 0;
}
// 用于判断模式串pattern在文本串text中出现了多少次
int kmp_times(char text[], char pattern[])
{
int times = 0;
int TextLen = strlen(text);
int PatLen = strlen(pattern);
// 当前比较的模式串字符位置
int j = 0;
// 比较文本串的每一个字符
for(int i=0; i<TextLen; ++i)
{
// 失配时沿着失配边走,直到可以匹配或回到模式串的第一个字符
while(j && text[i]!=pattern[j]) j = next[j];
// 比较当前文本串字符和移动后的模式串当前字符
if (text[i] == pattern[j]) ++j;
// 如果模式串的所有字符都比较相等了,则完成模式匹配
if (j == PatLen)
{
++times;
// 移动模式串
j = next[j];
}
}
return times;
}