首页 > 其他分享 >P3375 【模板】KMP 字符串匹配 题解

P3375 【模板】KMP 字符串匹配 题解

时间:2023-07-30 21:00:22浏览次数:42  
标签:AB 匹配 int s2 s1 KMP next 题解 P3375

前言

狗屁不是,建议别看!!!

 

题目链接

P3375 【模板】KMP 字符串匹配 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

 

分析

先给个例子

s1:ABCABCABB

s2:ABCABB

若使用朴素算法匹配,当匹配到

s1:ABCAB C ABB

s2:ABCAB B

时,朴素算法会跳出,然后匹配下一位。

最终匹配到

s1:ABC ABCABB

s2:    ABCABB

匹配成功

我们发现其中

s1:ABC AB CABB

s2:    AB CABB

AB二位在第一次匹配中已经匹配过了

 

那么如何简化该重复操作呢?

定义next数组(next是关键字,不要用作变量名)

next[i]表示的是s2在i之前的最长的完全相同的前缀后缀长度(不能为整个字符串)

例如:ABCAB

前缀有A、AB、ABC、ABCA

后缀有B、AB、CAB、BCAB

最长的完全相同的前缀后缀为AB,所以next=2

 

回到第一次匹配中,当匹配到

s1:ABCAB C ABB

s2:ABCAB B

时,即指针i(s1)=6,指针j(s2)=6;

由于next[5]=2,即s2中末尾AB(4,5)与开头AB(1,2)是等价的,并且s2末尾AB与s1中间的AB(4,5)是等价的

所以s1中间的AB可以与s2开头的AB匹配且最长

满足最长即前面的B、C都无法完成匹配

令此时j=next[j-1]+1,再进行下一次匹配

直到j=6(len s2)时匹配结束

 

那么如何计算next呢?

令i为当前所计算字符串的末尾,j为前缀的末尾

与两个字符串匹配类似

当a[i]!=a[j]时 令j=next[j-1]+1

 

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int N=1000006;
 5 
 6 char a[N],b[N];
 7 int ne[N];
 8 
 9 int main(){
10     scanf("%s %s", a+1, b+1);
11     int an=strlen(a+1),bn=strlen(b+1);
12     int j=0;//i,j指需要匹配的字符的前一个值
13     for(int i=1;i<bn;i++){
14         while(j>0&&b[j+1]!=b[i+1]) j=ne[j];
15         if(b[j+1]==b[i+1]) j++,ne[i+1]=j;
16     }
17     j=0;
18     for(int i=0;i<an;i++){
19         while(j>0&&b[j+1]!=a[i+1]) j=ne[j];
20         if(b[j+1]==a[i+1]) j++;
21         if(j==bn){
22             printf("%d\n", i+1-bn+1);
23             j=ne[j];
24         }
25     }
26     for(int i=1;i<=bn;i++) cout<<ne[i]<<" ";
27     return 0;
28 }

 

标签:AB,匹配,int,s2,s1,KMP,next,题解,P3375
From: https://www.cnblogs.com/Idtwtei/p/17591631.html

相关文章

  • 洛谷 P9489 ZHY 的表示法 题解
    Description给定\(\{x_n\}\),\(y\)为任意实数,求出在\([l,r]\)内\(\displaystyle\sum_{i=1}^{n}\lfloor\dfrac{y}{x_i}\rfloor\)有多少种取值。link:https://www.luogu.com.cn/problem/P9489Solution可以表示出的取值一定能被为某个\(x_i\)的倍数的\(y\)表示出。根据......
  • [ABC312] 题解 [D~Ex]
    [ABC312]题解[D~Ex]D-CountBracketSequences一个括号序列\(s\)包含(,),?,?可以填任意括号,问你填完后有多少种合法序列方式。这是一个Classical的括号序列DP,使用这个状态表示可以解决很多括号序列问题:\(dp[i][j]\)表示已经摆好了前\(i\)个字符,有\(j\)个没......
  • BZOJ 4321 queue2 题解
    在硬盘里翻到了当时没推完的这个题,今天补完了最后几步。题目链接:https://hydro.ac/d/bzoj/p/4321对任意相邻两个元素差的绝对值不为\(1\)的\(n\)阶排列计数。\(\mathcal{O}(n^2)\)做法是考虑按照值域由小到大逐步插入,记录\(f_{i,j}\)为长度为\(i\)的排列,一共有\(j\)......
  • bitwarden 私有化部署android无法登陆问题解决
    安卓版bitwarden安装使用中登陆提示“发生错误。Exceptionmessage:java.security.cert.CertPathValidatorException:Trustanchorforcertificationpathnotfound.”这个错误是因为Bitwarden的证书文件中缺少中间证书导致安卓系统的证书校验异常解决方式,生成带证书链的证......
  • CF1855B Longest Divisors Interval 题解
    原题链接:https://codeforces.com/contest/1855/problem/B题意:给定一个正整数n,找到满足该条件的区间[l,r]的长度的最大值:对于任意l<=i<=r,n均为i的倍数(多组数据)。思路:如果n是奇数,答案显然是1,因为任意两个连续的正整数一定会有一个2的倍数。将这一结论进行推广:......
  • Codeforces Round 889 (Div. 2) 题解
    \(6\)题只做出来\(1\)题,损失惨重A.DaltontheTeacher显然,答案一定和最初的不满意人数有关,所以输入的时候统计一下然后,将不满意的人的座位每两个人交换一次即可,交换次数就是答案如果不满意人数是奇数,那么答案还要加\(1\)时间复杂度\(O(n)\)(输入的复杂度)B.LongestD......
  • 【题解】[ABC312G] Avoid Straight Line(容斥,树上统计,dfs)
    【题解】[ABC312G]AvoidStraightLine题目链接[ABC312G]AvoidStraightLine题意概述给定一棵\(n\)个节点的树,第\(i\)条边连接节点\(a_i\)和\(b_i\),要求找到满足以下条件的三元整数组\((i,j,k)\)的数量:\(1\lei<j<k\len\);对于树上任意一条简单路径,都不同时经......
  • CF1855B Longest Divisors Interval 题解
    题意:给定一个数\(n\),求一个连续区间\([l,r]\)使得\(n\)是区间内每个数的倍数,最大化这个区间的长度(多组数据)。思路:逆向思考一波,(如果一个数\(x\)不是\(n\)的因数,那么\(x\)的倍数不能在区间内。举个例子,比如$n$是13,3不是13的因数,\(3,6,9,12\)也就不可能出现......
  • Codeforces Round 889 (Div. 1) 题解
    A1.Dual(EasyVersion)https://codeforces.com/contest/1854/problem/A1题意给定一个长度为\(n\)的序列\(a_1,a_2,\dots,a_n\),你可以做以下操作:选定两个下标\(i,j(1\leqi,j\leqn)\),\(i,j\)可以相同,然后\(a_i\leftarrowa_{i}+a_j\)。要求构造一种操作......
  • HDU 1312 Red and Black 题解
    //注意边界判断,调了好久#include<iostream>#include<queue>usingnamespacestd;#definecheck(x,y)(x<wx&&x>=0&&y<hy&&y>=0)structnode{intx,y;};charroom[23][23];intn,m,wx,hy,num;intdir[4][2]={......