把已经给出的串称为文本串,要在文本串中找的串称为模式串。特别地,前两位$(kmp[0],kmp[1])$为零。比如串$ABABAC$,它的$fail$应该为001230。
已知第$i$位的自动机$kmp[i]$,要求第$i+1$位的。设$j=kmp[i]$。$kmp[i]$一定在i前面,$kmp[i]$已经求好了。如果字符串的$i$和$j+1$位不同$(s2[i]≠s2[j+1])$,那么j不断地跳到自己的自动机$kmp[j]$,直到匹配上或$j=0$为止。如果匹配上,$f[i] = j+1$;否则如果还是$s2[i]≠s2[j+1]$,说明是$j=0$而不是匹配上了,那么$kmp[j] = 0$。

构建自动机:

  j=;
for (int i=;i<=lb;i++){
while(j&&b[i]!=b[j+])
//此处判断j是否为0的原因在于,如果回跳到第一个字符就不 用再回跳了
j=kmp[j];
//通过自己匹配自己来得出每一个点的kmp值
if(b[j+]==b[i])j++;
kmp[i]=j;
//i+1失配后应该如何跳
}

我们已经对该子串构建了一个自动机,当两个字符串相比较,如果失配,即$s1[i]!=s2[j+1]$就跳回,此时一定两位匹配$(j!=0)$或从头开始$(j=0)$,之后再匹配下一位即可。

运行自动机:

   int j;
j=;//j可以看做表示当前已经匹配完的模式串的最后一位的位置
//也可以理解为j表示模式串匹配到第几位了
for(int i=;i<=la;i++){
while(j&&b[j+]!=a[i])j=kmp[j];
//如果失配 ,那么就不断向回跳,直到可以继续匹配
if (b[j+]==a[i]) j++;
//如果匹配成功,那么对应的模式串位置++
if (j==lb) {
cout<<i-lb+<<endl;
j=kmp[j];
//继续匹配
}
}

完整代码:

 #include<iostream>
#include<cstring>
#define MAXN 1000010
using namespace std;
int kmp[MAXN];
int la,lb,j;
char a[MAXN],b[MAXN];
int main()
{
cin>>a+;
cin>>b+;
la=strlen(a+);
lb=strlen(b+);
for (int i=;i<=lb;i++)
{
while(j&&b[i]!=b[j+])
j=kmp[j];
if(b[j+]==b[i])j++;
kmp[i]=j;
}
j=;
for(int i=;i<=la;i++)
{
while(j>&&b[j+]!=a[i])
j=kmp[j];
if (b[j+]==a[i])
j++;
if (j==lb) {cout<<i-lb+<<endl;j=kmp[j];}
} for (int i=;i<=lb;i++)
cout<<kmp[i]<<" ";
return ;
}

Kmp--P3375 【模板】KMP字符串匹配的更多相关文章

  1. P3375 模板 KMP字符串匹配

    P3375 [模板]KMP字符串匹配 来一道模板题,直接上代码. #include <bits/stdc++.h> using namespace std; typedef long lo ...

  2. 洛谷P3375 [模板]KMP字符串匹配

    To 洛谷.3375 KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果 ...

  3. 【模板】字符串匹配的三种做法(Hash、KMP、STL)

    题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 输入输出格式 输入格式: 第一行为一个字符串,即为s1 第二行为一个字符串,即为s2 输出格式: 1行 ...

  4. 字符串KMP——用途广泛的字符串匹配算法 + 扩展KMP——特殊定义的字符串匹配

    引 入 引入 引入 " SY 和 WYX 在看毛片.(几 毛 钱买到的动作 片,毛 片) WYX 突然想回味一个片段,但是只记得台词里面有一句挺长的 " ∗ ∗ ∗ ∗ **** ...

  5. 字符串匹配Boyer-Moore算法:文本编辑器中的查找功能是如何实现的?---这应该讲的最容易懂的文章了!

    关于字符串匹配算法有很多,之前我有讲过一篇 KMP 匹配算法:图解字符串匹配 KMP 算法,不懂 kmp 的建议看下,写的还不错,这个算法虽然很牛逼,但在实际中用的并不是特别多.至于选择哪一种字符串匹 ...

  6. P3375 【模板】KMP字符串匹配

    P3375 [模板]KMP字符串匹配 https://www.luogu.org/problemnew/show/P3375 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在 ...

  7. 洛谷—— P3375 【模板】KMP字符串匹配

    P3375 [模板]KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next. (如 ...

  8. KMP字符串匹配 模板 洛谷 P3375

    KMP字符串匹配 模板 洛谷 P3375 题意 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.(如果 ...

  9. 洛谷P3375 - 【模板】KMP字符串匹配

    原题链接 Description 模板题啦~ Code //[模板]KMP字符串匹配 #include <cstdio> #include <cstring> int cons ...

  10. P3375【模板】KMP字符串匹配

    前言: 额……很久以前就写了KMP模板(只是半知不解),话说看完了manacher,再回过头看KMP,是真TM简单啊!字符串专题整体较抽象,所以必须牢记思路并时常复习 题目描述 如题,给出两个字符串s ...

随机推荐

  1. 修改Centos7的yum源

    以下为修改Centos7的yum源: 1. 备份原镜像文件,便于后期恢复 [root@keepmydream ~]# mv /etc/yum.repos.d/CentOS-Base.repo /etc ...

  2. 创建Git本地仓库

    一.获取Git仓库 安装好Git后即可创建Git本地仓库,开始项目的版本管理.有两种方法取得Git项目仓库:1.在现有项目或目录下导入所有文件到Git中:2.从一个服务器克隆一个现有的Git仓库. 1 ...

  3. kali打开networkmanager

    有时候可能在用网卡时,或者是其他情况下关闭了networkmanager,而要管理网络这个又是必须的,需要我们手动打开. 没有网络管理器是这样的: 有管理器是这样的: 不多废话了,用命令/etc/in ...

  4. {$DEFINE WANYI}

    var Form5: TForm5; {$DEFINE WANYI}implementation{$R *.dfm}procedure TForm5.Button1Click(Sender: TObj ...

  5. 安装ruby的一些坑

    之前一直下载不下来.是因为需要翻墙.

  6. 字符串题汇总(python3)

    1.最小编辑距离 假设有两个字符串s1和s2,计算通过增添.删除.替换三种操作后,从s1转变为s2所需要的操作次数. #coding=utf-8 class Solution: def editDis ...

  7. android studio 入门坑

    安装 android studio,碰到下面这个图片,直接跳过. 安装时候,选择自定义设置,里面可以配置 sdk 的存放位置. 新建工程后,gradle sync 比较慢,可以 修改工程中的 buil ...

  8. ORA-22813 ORA-06512

    ORA-22813:操作数值超出系统限制. 原因:   对象或集合值太大.SORT上下文中值的大小可能超过30k,或者可用内存的大小可能太大. 操作:  选择其他值并重试该操作. ORA-06512错 ...

  9. JS的数据类型、常量、变量、以及基本对象的知识总结

    第一部分.JS的常见数据类型,特别要注意的是JS中大小写要求很严格,一定要注意字段大小写. 1.字符串(String) 举例: var cellname = "Bill Gate" ...

  10. objectarx 批量倒角

    这个插件支持AcDbPolyline的倒角,封闭的和没封闭的都可以.刚开始做的时候,发现倒一个角借助云幽课堂里的代码就可以做,后来做一条从左开始画的非封闭的多段线,发现向上凹和向下凹的角不能同时被倒, ...