字符串匹配算法,在主串中寻找子串第一次出现时的下标。
暴力算法
以主串的每个字符作为起点向后比较,时间复杂度为O()。
KMP算法
特点:只回溯子串主串中不回溯
①匹配到此处发现不匹配
②检查子串中已经匹配的部分是否有前后缀相同的部分
③从子串前缀下一个位置再次匹配
next数组及其构建方法
如果每次都检查一遍子串中前后缀相同的部分有多长,很麻烦,所以引入next数组帮助我们快速找到匹配失败时,主串当前位置应该和子串的哪个位置重新开始匹配。
next数组的长度应和子串长度一样,下标为index的位置保存着当index+1匹配失败时,主串当前的位置应该和子串的哪个下标处的位置继续进行匹配。
初始化状态
i不等于j ① j != 0;j = next [j - 1] ② j == 0;next[i] = 0,i++;
i 等于 j,next[i] = j + 1,i++;j++
模板
跟上面的图略有不同,模式串的第一个字母对应着next数组index=1的位置。
// s[]是长文本,p[]是模式串,n是s的长度,m是p的长度
求模式串的Next数组:
for (int i = 2, j = 0; i <= m; i ++ )
{
while (j && p[i] != p[j + 1]) j = ne[j];
if (p[i] == p[j + 1]) j ++ ;
ne[i] = j;
}
// 匹配
for (int i = 1, j = 0; i <= n; i ++ )
{
while (j && s[i] != p[j + 1]) j = ne[j];
if (s[i] == p[j + 1]) j ++ ;
if (j == m)
{
j = ne[j];
// 匹配成功后的逻辑
}
}