ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Luogu P3375 【模板】KMP字符串匹配

2019-08-08 09:00:19  阅读:258  来源: 互联网

标签:include 匹配 int Luogu ++ len2 KMP P3375 失配


第一次写kmp是2月,写错但AC了...第二次是6月,才发现...

现在是8月,第三次 /cy


传送门

KMP (D.E.Knuth - J.H.Morris - V.R.Pratt) 也叫看…,是一种改进的字符串匹配算法,核心是在匹配失败后减少已经匹配过的部分重新匹配。

 

原理

KMP是通过一个f[](fail)——或者叫next的“失配函数”来实现的。

把已经给出的串称为文本串,要在文本串中找的串称为模式串。

首先,求出模式串的失配函数。

fail函数的含义是:在到这一位为止,前缀=后缀的最长长度是多少。

这里的=是指完全相同,比如ABCABC这样的,而不是对称,并且可以有重叠。

特别地,前两位(f[0],f[1])为零。

比如串$ABABAC$,它的fail应该为$001230$ (ABA和ABA重叠了也没事)。

假设已经求好了fail,那么,假设有文本串$ABABABAC$。

$ABABABAC$

$ABABAC$ ←到这里,发现配不上了

 

$ABABABAC$

  $ABABAC$ ←退回到第三位,再试试

 

$ABABABAC$

   $ABABAC$ ←成功

 

实现

求失配函数

求失配函数是一个自己和自己匹配的过程。

void getf() {
    f[0] = f[1] = 0;
    for(int i = 1; i < len2; i++) {
        int j = f[i];
        while(j && p[i]!=p[j]) j = f[j];
        if(p[i] == p[j]) f[i+1] = j+1;
        else f[i+1] = 0;
    }
}

已知第i位的失配函数f[i],要求第i+1位的。

设j=f[i]。f[i]一定在i前面,f[i]已经求好了。

如果字符串的i+1和j+1位不同(p[i]≠p[j]),那么j不断地跳到自己的失配函数f[j],直到匹配上或j=0为止。

如果匹配上,f[i+1] = j+1;

否则如果还是p[i]≠p[j],说明是j=0而不是匹配上了,那么f[j] = 0。

 

匹配

void kmp() {
    int j = 0;
    for(int i = 0; i < len1; i++) {
        while(j && s[i]!=p[j])j = f[j];
        if(s[i] == p[j])j++;
        if(j == len2) {
            printf("%d\n",1+i-len2+1);
            j = f[j];
        }
    }
}

文本串指针i,模式串指针j。

和刚刚类似,如果没匹配上,就不断把j跳到f[j]。

如果匹配上了,j往后一位,即j++。

 

完整代码如下

 

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#define MogeKo qwq
using namespace std;
#include<string>
const int maxn = 1e6+10;
int len1,len2,f[maxn];
string s,p;

void getf() {
    f[0] = f[1] = 0;
    for(int i = 1; i < len2; i++) {
        int j = f[i];
        while(j && p[i]!=p[j]) j = f[j];
        if(p[i] == p[j]) f[i+1] = j+1;
        else f[i+1] = 0;
    }
}

void kmp() {
    int j = 0;
    for(int i = 0; i < len1; i++) {
        while(j && s[i]!=p[j])j = f[j];
        if(s[i] == p[j])j++;
        if(j == len2) {
            printf("%d\n",1+i-len2+1);
            j = f[j];
        }
    }
}

int main() {
    cin>>s>>p;
    len1 = s.length();
    len2 = p.length();
    getf();
    kmp();
    for(int i = 1; i <= len2; i++)
        printf("%d ",f[i]);
    return 0;
}

 

标签:include,匹配,int,Luogu,++,len2,KMP,P3375,失配
来源: https://www.cnblogs.com/mogeko/p/11316385.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有