KMP学习(持续更新)

简介: KMP学习(持续更新)

文章目录

KMP

为什么需要使用KMP

相对于朴素匹配,我们想要跳过不可能成功的字符串比较,来减少比较的趟数。

怎么使用KMP

  1. 对于模式串p求出next数组
  2. 利用next数组,将模式串p与主串s作比较

什么是next数组

为什么要用`next`数组

什么是前缀,什么是后缀

前缀:简单来说,也就是,从第一个字母(必包括)开始往后看到最后一 个字母(不包括)为止的字符串的以第一个字母开头的子串

(比如“abab”的前缀有a,ab,aba);

后缀:简单来说,也就是,从最后一个字母(必包括)开始往前看到第一个字母(不包括)为止的字符串的子串

(比如“abab”的后缀有b,ab,bab);

最大公共子串长度:也就是前缀和后缀拥有的相同子串的最大长度

以“abab”为例:

模式串的各个子串 前缀 后缀 最大公共元素长度
a 0
ab a b 0
aba a, ab a, ba 1
abab a, ab, aba b, ab, bab 2

KMP模板(c语言)

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 1000005;
char s[maxn];
char p[maxn];
int next[maxn];
int pl , ml;
void getnext()
{
    next[0] = -1;
    for(int i=0,j=-1;i<pl;)
    {
        if(j==-1||p[i] == p[j]) next[++i] = ++j;
        else j = next[j];
    }
}
int Kmp()
{
    getnext();
    int i=0, j=0;
  while(i<ml&&j<pl){
    if(j==-1 || s[i] == p[j]){
      if(j==pl-1){ //匹配成功
        return i-pl+1+1; 
      }
      i++; j++;
    }
    else{
      j = next[j];
    }
  }
    return -1;
}
int main()
{
    scanf("%s",&s);
    scanf("%s",&p);
    ml = strlen(s);
    pl = strlen(p);
  printf("%d\n",Kmp());
    return 0;
}

2、串替换(C++类是实现KMP)

题目描述

给出主串、模式串、替换串,用KMP算法找出模式串在主串的位置,然后用替换串的字符替换掉模式串

本题只考虑一处替换的情况,如果你想做的完美一些,能够实现多处替换那可能需要考虑模式串和替换串长度不一致的情况

输入

第一个输入t,表示有t个实例

第二行输入第1个实例的主串,第三行输入第1个实例的模式串,第四行输入第1个实例的替换串

以此类推

输出

第一行输出第1个实例的主串

第二行输出第1个实例的主串替换后结果,如果没有发生替换就输出主串原来的内容。

以此类推

样例输入

4
aabbccdd
bb
ff
aaabbbccc
ddd
eee
abcdef
abc
ccccc
abcdef
abc
c

样例输出

aabbccdd
aaffccdd
aaabbbccc
aaabbbccc
abcdef
cccccdef
abcdef
cdef
#include <iostream>
#include <string>
using namespace std;
class myString
{
private:
  int size;
  void GetNext(string p,int next[]);
  int KMPFind(string p,int pos,int next[]); 
public:
  string mainstr;
  myString();
  ~myString();
  void SetVal(string sp);
  int KMPFindSubstr(string p,int pos);
  void tihuan(string p,int pos,int molen);
};
myString::myString()
{
  size = 0;
  mainstr="";
}
myString::~myString()
{
  size = 0;
  mainstr="";
}
void myString::SetVal(string sp)
{
  mainstr = "";
    mainstr.assign(sp);
    size  = mainstr.length();
}
void myString::GetNext(string p,int next[])
{
  next[0] = -1;
  int i = 0,now =-1;
  while(i<int(p.length()))
  {
    if(now==-1||p[i]==p[now])
    {
      i++;
      now++;
      next[i]=now;
    }else
    {
      now = next[now];
    }
  }
} 
int myString::KMPFind(string p,int pos,int next[])
{
  int i=pos,j=0;
  while(i<size&&j<int(p.length()))
  {
    if(j==-1||mainstr[i]==p[j])
    {
      i++;
      j++;
    }else
    {
      j=next[j];
    }
  }
  if(j==int(p.length()))
        return i-j+1;
    else return 0;
}
int myString::KMPFindSubstr(string p,int pos)
{
  int i;
  int L=p.length();
  int *next = new int [L];
  GetNext(p,next);
//  for(int i=0;i<L;i++)
//  {
//    cout<<next[i]<<" ";
//   } 
//   cout<<endl;
   int v=-1;
   v = KMPFind(p,0,next);
   delete []next;
   return v;
}
void myString::tihuan(string p,int pos,int molen)
{
  int len = p.length();
  string sub1 = mainstr.substr(0,pos);
  string sub2 = mainstr.substr(pos+molen);
  mainstr = sub1+p+sub2; 
}
int main()
{
  int t;
  cin>>t;
  while(t--)
  {
    string mainstr,mostr,tihuanstr;
    cin>>mainstr>>mostr>>tihuanstr;
    myString ms;
    ms.SetVal(mainstr);
    int molen = mostr.length();
    int pos = ms.KMPFindSubstr(mostr,0)-1;
    cout<<ms.mainstr<<endl;
    if(pos!=-1)
    {
      ms.tihuan(tihuanstr,pos,molen);
    }
    cout<<ms.mainstr<<endl;
  }
 } 


相关文章
2022 数据结构与算法《王道》学习笔记 (十一)KMP算法 详细归纳总结 改进的模式匹配算法
2022 数据结构与算法《王道》学习笔记 (十一)KMP算法 详细归纳总结 改进的模式匹配算法
2022 数据结构与算法《王道》学习笔记 (十一)KMP算法 详细归纳总结 改进的模式匹配算法
|
存储 人工智能 算法
2022 数据结构与算法《王道》学习笔记 (十)串 KMP算法 串的总结 课后习题笔记
2022 数据结构与算法《王道》学习笔记 (十)串 KMP算法 串的总结 课后习题笔记
|
算法
【手把手带你学会KMP算法】
【手把手带你学会KMP算法】
86 0
|
算法 容器
算法-蓝桥基础知识-持续更新中....
算法-蓝桥基础知识-持续更新中....
|
算法 Java
算法笔记(一)——KMP算法
算法笔记(一)——KMP算法
算法笔记(一)——KMP算法
|
算法 Java 索引
数据结构与算法之美 | 别怕,有我!KMP 算法详解
为什么我认为 KMP 算法就是个动态规划问题呢,等会再解释。对于动态规划,之前多次强调了要明确 dp 数组的含义,而且同一个问题可能有不止一种定义 dp 数组含义的方法,不同的定义会有不同的解法。
数据结构与算法之美 | 别怕,有我!KMP 算法详解
|
机器学习/深度学习 算法 C++
算法笔记(一)—— KMP算法练习题
算法笔记(一)—— KMP算法练习题
算法笔记(一)—— KMP算法练习题
|
存储 算法
一文吃透KMP
本文主要为了解决字符串匹配问题,在解决字符串匹配问题的方法中,最为出名的就是BF(暴力)解法和KMP解法,两者相比,前者更易理解但效率没有后者高。 本文通过先介绍BF解法,来为KMP解法做铺垫,使得两种解法都更易理解;一般题目中会涉及两个字符串,一个是文本串(haystack),另一个是模式串(needle),需要在文本串中找到模式串,如果找到了就返回模式串在文本串出现位置的下标,如果没有出现就返回-1.
147 0
一文吃透KMP
|
算法
KMP算法总结笔记
KMP算法总结笔记
82 0
KMP算法总结笔记
|
算法
代码随想录算法训练营第八天 | 字符串
代码随想录算法训练营第八天 | 字符串
85 0