首页 > 其他分享 >KMP 字符匹配

KMP 字符匹配

时间:2023-10-07 09:56:43浏览次数:31  
标签:字符 匹配 int 代码 算法 nex KMP

忘了具体什么时候写的,应该是 2023.8 初

这算是个算法复习,因为我太菜了以前学的都不会了。

KMP 字符匹配

有一说一这个我讲不来,大概意思就列这好了:

Knuth(D.E.Knuth)&Morris(J.H.Morris)&Pratt(V.R.Pratt) 提出的字符串匹配算法,简称 KMP。

KMP 算法应该是最基础的字符串匹配算法了,基本原理是最大化利用已经处理过的数据,减少重复运算,然后达到线性复杂度。

KMP 算法解决的最一般的问题就是给定一个长串和一个短串,问你短串在长串中出现的位置和次数。如果我们用朴素的暴力算法自然就是一个一个比对过去,如果有错误就重新开始,如果正确就输出,大概代码为:

cin>>s>>l;
for(int i=0;i<s.length();i++){
    for(int j=0;j<l.length();j++){
        if(s[i+j]!=l[j])break;
        if(j==l.length()-1)printf("%d\n",i);
    }
}

然后这个代码居然一不小心给 KMP 模板过了?(border 是用 KMP 求的)

咳咳,反正这个代码在最优情况下虽然也是线性,但是显然很容易卡到 \(O(|s||l|)\) 的复杂度,原因是什么呢?

比如:

abcab
abcacababcab

正常我们是要一步一步比对的,发现错误之后移动一格继续匹配,而我们发现前四个都相同,我们这时不需要比较前四个,而是直接移动到查找不一样的。

   abcab
abcacababcab

反正大概就是对于前后缀相同已经判断过的可以不用继续判断,而是通过前一位的答案跳到一个位置。

那怎么知道应该跳到哪个位置?其实只需要先跟自己比较搞出一个 nex 数组即可。

nex 数组存的是这一位之前的最大前缀等于后缀的长度(非本身)。转移只需要找比较上个位置的 nex 的下一个是否相同即可,具体看代码吧。

\(Code\)

int nex[1000002],n,m;
char s[1000004],l[1000002];
void init(){
   int los=0;
   for(int i=2;i<=m;i++){
       while(los&&l[i]!=l[los+1])los=nex[los];//不匹配跳到上一个位置
       if(l[los+1]==l[i])los++;//匹配就加
       nex[i]=los;//更新
   }
}
int main(){
   scanf("%s%s",s+1,l+1);
   n=strlen(s+1),m=strlen(l+1);
   init();
   int j=0;
   for(int i=1;i<=n;i++){
       while(j&&l[j+1]!=s[i])j=nex[j];//不匹配跳上一个
       if(l[j+1]==s[i])j++;
       if(j==m)printf("%d\n",i-m+1),j=nex[j];//找完了跳回去看看能不能继续匹配
   }
   for(int i=1;i<=m;i++)printf("%d ",nex[i]);
}

标签:字符,匹配,int,代码,算法,nex,KMP
From: https://www.cnblogs.com/NBest/p/17745589.html

相关文章

  • PostgreSQL 的模式匹配与正则表达式
    一、PostgreSQL实现模式匹配的方法LIKESIMILARTOPOSIX风格的正则表达式模式匹配函数substring二、LIKE操作符只有在匹配整个字符串时返回真符号描述%任意0个或任意个字符_任意一个字符\%%\__postgres=#select*fromtest_zhengze;id|......
  • 字符串排序
    方法1:直接用数组排序publicclassStringSort{publicstaticvoidmain(String[]args){String[]strings={"abc123","abc+1234","ababab--1"};//对每个字符串计算字母字符个数和数字字符个数,并按照字母数字比和字符串本身大小排序Arra......
  • 如何检查一个字符串是否包含子字符串的JavaScript方法?
    内容来自DOChttps://q.houxu6.top/?s=如何检查一个字符串是否包含子字符串的JavaScript方法?通常,我会期望有一个String.contains()方法,但似乎没有这个功能。有什么合理的方式来检查这个吗?ECMAScript6引入了String.prototype.includes:conststring="foo";constsubstri......
  • 【HTML专栏3】!DOCTYPE、lang、字符集的作用
    本文属于HTML/CSS专栏文章,适合WEB前端开发入门学习,详细介绍HTML/CSS如果使用,如果对你有所帮助请一键三连支持,对博主系列文章感兴趣点击下方专栏了解详细。博客主页:DuckBro博客主页系列专栏:HTML/CSS专栏关注博主,后期持续更新系列文章如果有错误感谢大家批评指出,一定及时修改感谢......
  • 每个字符串从'/'到最后的内容都被替换为''
    list_1=['产品类型','后续机台','重量','可生产温度/℃','预计自然冷却时间/h','预计单面风机风机强冷时间/h','预计双面风机风机强冷时间/h']#请使用正则表达式给出pattern使得每个字符串从'/'到最后的内容都被替换为'',最终结果为['产品类型......
  • 基础算法--字符串
    \(KMP\)\(KMP\)算法(Knuth-Morris-Pratt算法)是一个著名的字符串匹配算法,效率很高,但是确实有点复杂。基本概念\(1\)、s[]是模式串,即比较长的字符串。\(2\)、p[]是模板串,即比较短的字符串。(这样可能不严谨。。。)\(3\)、“非平凡前缀”:指除了最后一个字符以外,一个字符串的全......
  • 【字符串】【哈希】ABC284F ABCBAC 题解
    ABC284F这题的正解是\(Z\)函数。如果\(str=T+T\)的话,若可以找到连续的分别长为\(n\)的两段,且这两段可通过\(1\)次翻转变为相同的字符串,那么便一定有解,否则无解。暴力判断是\(\mathcal{O}(n)\)的,时间复杂度直接上天。可以用哈希\(\mathcal{O}(1)\)地判断出两个......
  • 前端 跳动的字符
    #loginTextspan{top:20px;/*让文本从上方留出15像素的距离*/position:relative;/*相对定位,为下面的动画做准备*/transform:translate(-50%,-50%);/*将元素置中,必须和position同时使用*/font-family:"楷体",sans-serif;/*设置字体,首选楷体......
  • WebKit Inside: CSS 样式表的匹配时机
    WebKitInside:CSS的解析介绍了CSS样式表的解析过程,这篇文章继续介绍CSS的匹配时机。无外部样式表内部样式表和行内样式表本身就在HTML里面,解析HTML标签构建DOM树时内部样式表和行内样式就会被解析完毕。因此如果HTML里面只有内部样式表和行内样式,那么当DOM树......
  • C# 中的字符串内插
    vardate=newDateTime(1731,11,25);Console.WriteLine($"On{date:dddd,MMMMdd,yyyy}LeonhardEulerintroducedtheletteretodenote{Math.E:F5}inalettertoChristianGoldbach.");//Expectedoutput://OnSunday,November25,1731Leonh......