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

news2024/11/29 11:45:14

【模板】KMP字符串匹配

题目描述

给出两个字符串 s 1 s_1 s1 s 2 s_2 s2,若 s 1 s_1 s1 的区间 [ l , r ] [l, r] [l,r] 子串与 s 2 s_2 s2 完全相同,则称 s 2 s_2 s2 s 1 s_1 s1 中出现了,其出现位置为 l l l
现在请你求出 s 2 s_2 s2 s 1 s_1 s1 中所有出现的位置。

定义一个字符串 s s s 的 border 为 s s s 的一个 s s s 本身的子串 t t t,满足 t t t 既是 s s s 的前缀,又是 s s s 的后缀。
对于 s 2 s_2 s2,你还需要求出对于其每个前缀 s ′ s' s 的最长 border t ′ t' t 的长度。

输入格式

第一行为一个字符串,即为 s 1 s_1 s1
第二行为一个字符串,即为 s 2 s_2 s2

输出格式

首先输出若干行,每行一个整数,按从小到大的顺序输出 s 2 s_2 s2 s 1 s_1 s1 中出现的位置。
最后一行输出 ∣ s 2 ∣ |s_2| s2 个整数,第 i i i 个整数表示 s 2 s_2 s2 的长度为 i i i 的前缀的最长 border 长度。

样例 #1

样例输入 #1

ABABABC
ABA

样例输出 #1

1
3
0 0 1

提示

样例 1 解释

对于 s 2 s_2 s2 长度为 3 3 3 的前缀 ABA,字符串 A 既是其后缀也是其前缀,且是最长的,因此最长 border 长度为 1 1 1

数据规模与约定

本题采用多测试点捆绑测试,共有 3 个子任务

  • Subtask 1(30 points): ∣ s 1 ∣ ≤ 15 |s_1| \leq 15 s115 ∣ s 2 ∣ ≤ 5 |s_2| \leq 5 s25
  • Subtask 2(40 points): ∣ s 1 ∣ ≤ 1 0 4 |s_1| \leq 10^4 s1104 ∣ s 2 ∣ ≤ 1 0 2 |s_2| \leq 10^2 s2102
  • Subtask 3(30 points):无特殊约定。

对于全部的测试点,保证 1 ≤ ∣ s 1 ∣ , ∣ s 2 ∣ ≤ 1 0 6 1 \leq |s_1|,|s_2| \leq 10^6 1s1,s2106 s 1 , s 2 s_1, s_2 s1,s2 中均只含大写英文字母。

分析

  1. KMP算法就是解决字符串匹配问题,然后这个算法最主要的就是next数组的求解;下面介绍下next数组,以及怎么去求;
  2. 首先要明白next数组存的是模式串的最长相等前后缀的长度,求next和文本串没有联系;next数组存的是,每个位置的字符他之前的字符串的最长相等前后缀的长度,next[3]=2表示模式串中,索引为[0~3]的字符组成的子串,它的最长相等前后缀长度为2;前缀是一定包含首字母,不包含尾字母的所有子串;后缀是一定包含尾字母,不包含首字母的所有子串;
  3. 举个求模式串的next例子:文本串为aabaabaaf,模式串为aabaaf,那么next[0]=0,也就是子串a的最长相等前后缀的长度为0,因为a的前缀、后缀既包含了尾字母,又包含了首字母;next[1]=1,因为子串aa的前缀是a,后缀是a,所以子串aa的最长相等前后缀的长度为1;next[2]=0,因为子串aab的前缀有a、aa,后缀有b、ab,没有相等前后缀,故其值为0;next[3]=1,因为子串aaba的前缀有:a、aa、aab,后缀有a、ba、aba,所以子串aaba的最长相等前后缀的长度为1;next[4]=2,因为子串aabaa的前缀有:a、aa、aab、aaba,后缀有a、aa、baa、abaa,所以子串aabaa的最长相等前后缀的长度为1;next[5]=0,因为子串aabaaf的前缀有:a、aa、aab、aaba、aabaa,后缀有f、af、aaf、baaf、abaaf,所以子串aabaaf的最长相等前后缀的长度为0;
  4. 同时上面的分析我们得到了模式串aabaaf的next数组,为:0 1 0 1 2 0 ,那么next有什么用呢?还是上面的例子文本串为aabaabaaf,模式串为aabaaf,可以发现当和文本串匹配到aabaab这里时发现,文本串的b和模式串最后的f不匹配,这时模式串直接回退到 不匹配的字符的前一个字符的next值;也就是回退到模式串索引为4的a字符的next值的位置,此时next[j-1]=2,所以回退到模式串索引为2的位置,也就是b,然后模式串从b开始继续向后匹配文本串继续从上次中断的位置b继续开始,和模式串进行比对),最后成功匹配;
  5. 有的地方可能为了方便不匹配时回退(也就是直接j=next[j],而不是j=next[j-1]),让前缀表整体右移了,然后第一位默认为-1,也就是-1 0 1 0 1 2,但这里就不后移了;
  6. 代码实现——求next初始化i=1,j=0,i为后缀末尾,j为前缀末尾,然后next[0]=0;然后for从i=1开始,遍历模式串,②如果前后缀不匹配,那就让前缀的末尾j回退到不匹配的字符的前一个字符的next值;③如果前、后缀匹配,那就j++④更新当前i的next的值,其值就为j;
  7. 代码实现——判断文本串、模式串匹配:遍历文本串,i指向当前遍历到的文本串的位置,j为遍历到的模式串的位置;和求next一样,先初始化i,j,都初始为0,然后判断,如过不匹配(j > 0 && s1[i] != s2[j]),那就让j回退到next[j-1],匹配的话(s2[i] == s2[j])j++;然后判断是否已经完全匹配(j == s2.size()),是的话输出首字母在当前文本串所匹配的子串首字母位置;
  8. 题意:此题第一问就是判断文本串和模式串是否匹配,如果匹配输出首字母在当前文本串所匹配的子串首字母位置(从1开始计算的,所以输出的时候是+2,i - s2.size() + 1表示模式串首字母所在匹配的文本串的位置,由于从1开始所以多加1,就变成了i - s2.size() + 2 );第二问就是输出一下next数组;
#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 10;

string s1, s2;
int nex[N];//最长相等前后缀的长度

//求模式串s2的next数组
void getNext() {
    //1. 初始化, i为后缀末尾,j为前缀末尾
    int i = 1, j = 0;
    nex[0] = 0;
    for (i = 1; i < s2.size(); ++i) {
        //2. 前后缀不相同,多次回退,所以要用while
        while (j > 0 && s2[i] != s2[j]) {
            //j回退到 next[j-1]
            j = nex[j - 1];
        }
        //3. 前后缀相同
        if (s2[i] == s2[j])
            j++;
        //4. 更新i的next
        nex[i] = j;
    }
}

int main() {
    cin >> s1 >> s2;
    getNext();
    int j = 0;//模式串s2
    for (int i = 0; i < s1.size(); ++i) {//遍历文本串
        //不匹配
        while (j > 0 && s1[i] != s2[j]) {
            //回退到不匹配的那个字符的前一个字符所对应的next值
            j = nex[j - 1];
        }
        //匹配
        if (s1[i] == s2[j])
            j++;
        //说明全部匹配完成
        if (j == s2.size()) {
            cout << i - s2.size() + 2 << endl;
        }
    }
    for (int i = 0; i < s2.size(); ++i) {
        cout << nex[i] << " ";
    }
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/142396.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring中的@Value注解

文章目录**概述****使用方式**基于配置文件的注入基于非配置文件的注入注入普通字符串注入操作系统属性注入表达式结果注入其他bean属性注入URL资源概述 本文配置文件为yml文件 在使用spring框架的项目中&#xff0c;Value是经常使用的注解之一。其功能是将与配置文件中的键对应…

MANA OASIS加持,毫末算力极致优化,训练成本降低100倍

2023年1月5日&#xff0c;第七届HAOMO AI DAY在北京举办。正值岁末年初&#xff0c;中国自动驾驶届开年盛会精彩来袭。本届AI DAY上&#xff0c;毫末分享了2022年三大战役稳健收官成果&#xff0c;展望2023年全球自动驾驶发展趋势&#xff0c;并发布毫末技术、产品最新成果。 &…

基于java ssm springboot选课推荐交流平台系统设计和实现

基于java ssm springboot选课推荐交流平台系统设计和实现 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 欢迎点赞 收藏 ⭐留言 文末获取源码联系方式 文章目录基于java ss…

docker 看懂这一篇文章就够了

docker就像是手机的应用商店&#xff0c;有了应用商店&#xff0c;就不用自己一个app一个app(微服务开发所需要的中间件)去百度搜索下载&#xff0c;可以在应用商店里面一键下载&#xff08;使用简单的docker命令即可&#xff09; 总之就是一句话&#xff0c;docker pull 镜像…

ubuntu20.04安装4090驱动

实验室配置了一台新主机&#xff0c;现在安装好了20.04&#xff0c;为了安装4090的驱动查找了很多资料。接下来记录一下安装4090驱动的过程&#xff0c;为方便未来安装其他的显卡驱动。 首先推荐一个视频&#xff0c;在为查找了很多资料后&#xff0c;发现这个视频讲的实在是太…

【SQL】无列名查询表中数据

目录 【SQL】无列名查询表中数据 拓展 如果mysql中 information_schema 使用不了&#xff0c;怎么查询所有的数据库名&#xff0c;表名&#xff1f; 【SQL】无列名查询表中数据 有些时候&#xff0c;我们可能获取不了mysql数据库&#xff0c;表中的字段名称&#xff0c;那么…

基于Java+SpringBoot+vue+element实现扶贫助农政策平台系统

基于JavaSpringBootvueelement实现扶贫助农政策平台系统 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写> 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术…

0基础快速入门Python数据挖掘

推荐教程&#xff1a;4天快速入门Python数据挖掘 课程简介 该阶段主要是介绍一些数据科学领域用Python语言实现的基础库&#xff0c;如简洁、轻便的数据可视化展示工具Matplotlib&#xff0c;高效的运算工具Numpy&#xff0c;方便的数据处理工具Pandas&#xff0c;为人工智能阶…

疑难杂症之anaconda虚拟环境安装还有anaconda无数次的卸载重装

教训&#xff1a;使用虚拟环境无数次重装& 卸载彻底删除命令&#xff1a;打开cmd --> 输入一下命令conda install anaconda -cleananaconda -clean --yes生成的备份文件夹可以删除**手动删除anaconda环境路径下的envs 和pkgs文件**然后从卸载界面点击正常卸载anaconda即…

Anaconda下载库(安装包)、创建虚拟环境等

conda install pak # 安装包&#xff0c;pak代表包名&#xff0c;可依次安装多个包或指定版本&#xff0c;包名之间空格分开&#xff1b; conda remove pak # 移除指定包 conda update pak # 更新包 conda upgrade --all # 更新所以包 conda search pak # …

【数组】leetcode59.螺旋矩阵II(C/C++/Java/Js)

leetcode59.螺旋矩阵II1 题目2 思路3 代码3.1 C版本3.2 C版本3.3 Java版本3.4 JavaScript版本4 总结&#xff1a;1 题目 题源链接 给你一个正整数 n &#xff0c;生成一个包含 1 到 n2 所有元素&#xff0c;且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1…

shell脚本之sed练习题

把/etc/passwd 复制到/root/test.txt&#xff0c;用sed打印所有行 #使用cp命令将/etc/passwd的内容复制到/root/test.txt中 [rootWilliam ~]# cp /etc/passwd /root/test.txt#采用sed命令将其打印出来 [rootWilliam ~]# sed -n p test.txt打印test.txt的3到10行 [rootWilliam…

都2023年了,还不知道怎么学习网络安全?来看看吧,很难找全的

前言 最近收到不少关注朋友的私信和留言&#xff0c;大多数都是零基础小友入门网络安全&#xff0c;需要相关资源学习。其实看过的铁粉都知道&#xff0c;之前的文里是有过推荐过的。新来的小友可能不太清楚&#xff0c;这里就系统地叙述一遍。 01.简单了解一下网络安全 说白…

逆向-还原代码之little-or-big (Interl 64)

// 源代码 #include <stdio.h> /* * 2016/9/29 yu liang. */ int test_one(void) { int i1; char *p(char *)&i; if(*p1) printf("Little_endian\n"); // Little_endian else printf("B…

cmake报错:Unsupported protocol

现象 最近在用cmake编译Apache arrow时&#xff0c;竟然报了错&#xff1a; 排查过程 最开始在网上直接搜“Unsupported protocol”&#xff0c;查到的说是因为安装的curl不支持https&#xff0c;需要先使用如下命令查询curl支持的协议&#xff1a; curl -V然而查出来却是…

微服务面试必问的Dubbo,这么详细还怕自己找不到工作?

前言 互联网的不断发展&#xff0c;网站应用的规模不断扩大&#xff0c;常规的垂直应用架构已无法应对。 服务化的进一步发展&#xff0c;服务越来越多&#xff0c;服务之间的调用和依赖关系也越来越复杂&#xff0c;诞生了面向服务的架构体系(SOA)&#xff0c; 也因此衍生出…

财富自由、技术瓶颈、面试技巧,找另一半...这些程序员最关心的问题,AI的回答神了!

距离ChatGPT发布已经好几周了&#xff0c;我还沉迷在和它的聊天当中&#xff0c;每天一遇到问题&#xff0c;我的第一反应就是先问问ChatGPT的建议&#xff0c;作为一名程序员&#xff0c;我们可能有很多问题或困惑&#xff0c;我也问问了它&#xff0c;整理了一些比较有代表性…

Nodejs三层架构的封装

nodejs三层架构开发模式 项目结构 依次在每个目录添加代码 1.在dao层下创建database.js模块,里面存放的是连接数据库的模块代码 const {connect,connection} require(mongoose); // 设置要连接的 MongoDB 服务器地址(studentsManage:要连接的数据库名称) const dbURI mong…

Unity InputSystem基础

一些概念 Action Maps 一组Action的集合为一个Action Map。可以同时有多个Action Map&#xff0c;可以进行切换&#xff0c;也可以同时运行&#xff08;监控&#xff09;。例如可以使用joystick控制角色移动&#xff0c;也可以使用joystick控制菜单。通过切换Action Map&#x…

别小看 Log 日志,它难住了我们组的架构师

Slf4j slf4j 的全称是 Simple Loging Facade For Java&#xff0c;它仅仅是一个为 Java 程序提供日志输出的统一接口&#xff0c;并不是一个具体的日志实现方案&#xff0c;就比如 JDBC 一样&#xff0c;只是一种规则而已。所以单独的 slf4j 是不能工作的&#xff0c;必须搭配…