首页 > 其他分享 >KMP

KMP

时间:2023-09-07 19:46:14浏览次数:32  
标签:子串 字符 匹配 后缀 位置 Next KMP

KMP

1.作用

用于字符串匹配,在文本串 $S$ 中查找模式串 $P$ 。(较短的或许直接调用函数?)

2.过程(结合画图分析)

KMP算法相较于朴素算法的精髓在个人看来在于不回退指针 $i$,以及 $Next[i]$ (模式串在位置 $i$ 以前的子串的最长公共前后缀)。

为什么不用回退 $i$ ?

在 $i$ (匹配失败的位置)之前模式串匹配成功的字符有两种情况:每个字符都不相同、部分字符相同

每个字符都不相同 :因为相应位置的字符已经和文本串匹配,那么可以表明已经匹配的字符中不会有一个位置可以使文本串与模式串匹配。

部分字符相同 : (再次划分)

相同部分在两端(即前后缀):看下面分析。(先写的下面发现忘了这个。。)

相同部分不在两端(A,B至少有一个不是前后缀):将相同的部分在前面的一段称为子串 $A$ ,后面的称为子串 $B$,那么假设把 $A$ 移动到 $B$ 的位置:那么如果 $A$ 不是前缀,则在 $A$ 之前的那部分无法与原本在 $B$ 之前的子串匹配,如果 $B$ 不是后缀,那么在 $A$ 之后的那部分无法与原本在 $B$ 之后的子串相匹配(注意只有 $A$ ,B这部分相等,如果匹配说明它们的长度还能更长),因此也是无法找到位置使得文本串与模式串匹配。

综上所述没有回退 $i$ 的必要。

为什么要找出最长公共前后缀?

假设字符串在第 $i+1$ 位时匹配不成功,那么在 $[0,i]$ 这个区间上的字符串是可以匹配成功的,假设存在某段前缀等于某段后缀(注意前后缀不包括字符串本身),那么我们可以将这段前缀往右移,到原本后缀的位置,那么此时 原本的前缀 可以 和 原本的后缀相匹配的 那一段文本串的子串 匹配,如果通过移动使得原本不匹配的位置又可以成功匹配,那么就继续往后匹配,否则继续看 移动后的模式串 在当前位置的子串 是否还有相等的前后缀,如果有则继续上述操作,否则让模式串重新开始匹配。

以下是找出最长公共前后缀的代码

    const int N = 1e6 + 10;
    Next[N];
    string s; cin >> s;
    Next[0] = -1;
    for (int i = 1, j = -1; i < n; i++) {
        while (j != -1 && s[i] != s[j + 1])j = Next[j];
        if (s[i] == s[j + 1])j++;
        Next[i] = j;
    }

匹配

for (int i = 1, j = 0; i <= n; i++) {
        while (j && s[i] != p[j + 1])j = Next[j];
        if (s[i] == p[j + 1])j++;
        if (j == m) {
            cout << i - m + 1 << endl;
        }
    }

标签:子串,字符,匹配,后缀,位置,Next,KMP
From: https://www.cnblogs.com/yxyxyxyxyx/p/17685899.html

相关文章

  • KMP算法详解
    呼——终于看懂了KMP——磕了三天了。题目直达Q:KMP是干什么的?是查找字符串用的,可以查找到\(S2\)字符串在\(S1\)字符串中出现的位置(当然,你可以统计出次数)。Q:那复杂度是多少的?通常,我们认为他的复杂度是\(O(|S1|)\),虽然有点常数。常规的的比较方法是直接比较,枚......
  • kmp的简单应用
    Smiling&Weeping----我只为你一个人写过月亮 题目链接:P4824[USACO15FEB]CensoringS-洛谷|计算机科学教育新生态(luogu.com.cn)题目思路:编码时,在正常的kmp中加入以下两条:1.定义一个和S一样大的数组记录每个字符对应的j值,用于删除一个......
  • 拓展kmp
    Smiling&Weeping----我从不觉得暗恋是苦涩的,对一个人的喜欢藏在眼睛里,透过它,世界都变得更好看了。题目:P5410......
  • kmp模板
    Smiling&Weeping----深情是我担不起的重任,情话只是偶然兑现的谎言 题目:Problem-2087(hdu.edu.cn)就是简单的kmp,再加上一个判断是否和上一个重复现在上模板:Talkischeap,showmethecode1#include<iostream>2#include<cstr......
  • KMP算法--解决字符串匹配问题--模式串是否在文本串出现过
    KMP算法--解决字符串匹配问题--模式串是否在文本串出现过*利用之前判断过的信息,通过next数组保存最长公共子序列的长度*搜索词/模式串移动的位数=已匹配的字符数-对应的部分匹配值在韩的例子里ABCDABD初次匹配匹配了ABCDAB6位,对应2,所以移动6-2=4位e.g.文本串aabaabaaf......
  • 串的匹配算法:Brute-Force 与 KMP
    目录串的匹配算法:Brute-Force与KMPBrute-Force(布鲁特-福斯)算法KMP算法参考文献串的匹配算法:Brute-Force与KMP串的匹配算法是求子串在主串位置的算法。本次介绍的算法是在指定了从主串特定位置后寻找第一个匹配字串的位置。在介绍算法前,先定义几个变量:主串S、字串T、要求......
  • 算法学习-exKMP
    什么是exKMPexKMP(Z-Algorithm)是一个可以在\(O(|S|+|T|)\)的时间复杂度内求出\(T\)串的每个后缀与\(T\)的LCP(最长公共前缀)\(T\)串和\(S\)串每个后缀的LCP。的算法。算法过程首先回忆一下KMP算法,求\(nxt\)数组和两串匹配本质上没啥区别。所以我们尝试也将......
  • 「学习笔记」扩展 KMP(Z 函数)
    对于个长度为\(n\)的字符串\(s\)。定义\(z[i]\)表示\(s\)和\(s[i,n-1]\)(即以\(s[i]\)开头的后缀)的最长公共前缀(LCP)的长度。\(z\)被称为\(s\)的Z函数。这里注意,在Z函数中,\(z[0]=0\),但是根据LCP的定义,\(z[0]=n\),具体应该为何值,根据题目意思来判断。本文更偏......
  • KMP 字符串匹配 学习笔记
    前言最近才发现自己写了后缀数组,但并没有其他的字符串算法,今天先把\(KMP\)字符串匹配先讲一下。算法核心对于字符串匹配,最朴素的方法就是一个字符一个字符地匹配,找到不同的就直接换一个地方匹配。我们先来看一组样例:\(ababababe\)\(ababe\)对于这组样例,暴力的方法就是直......
  • 洛谷P5410 【模板】扩展 KMP(Z 函数)题解
    题目链接P5410【模板】扩展KMP(Z函数)-洛谷|计算机科学教育新生态(luogu.com.cn) 分析先考虑z数组设nx[i]为字符串b与b以b[i]开头的后缀最长公共前缀设i为当前需要求的位置当前i+nx[i]-1的最大值所对应的i为q p为i对应的位置当i大于q+nx[q......