KMP
一、问题
给出两个字符串
现在请你求出
二、常规方法
对于平常的字符串匹配,我们一般会这样:
-
如果
-
否则
即最平常的暴力算法
然而这种算法最坏是
三、优化(即KMP)
我们可以先举个对上面方法非常不友好的栗子:
每次
从上面我们可以看出,因为
那如何把前面的
我们可以发现,前面的
如果能够只用判断没有判断过的
即我们在匹配失败(后记为失配)后如何移动下面的字符串的指针,这尤为重要
假使我们知道了这些数值,我们便可以在每一次失配的时候将指针向前跳。
那我们如何求这个指针跳跃的数组
其实
下面给一组例子:
下标 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|
模式串 | A | B | A | B | A | B | C |
失配数组 | 0 | 0 | 1 | 2 | 3 | 4 | 0 |
前后缀 | 无 | 无 | A | AB | ABA | ABAB | 无 |
至于求法不太说得清楚,可以看一下下面的代码(抱歉)
#include<iostream> #include<string> using namespace std; const int NN = 1e6 + 8; string s1,s2; int jump[NN]; int main(){ cin>>s1>>s2; s1 = ' ' + s1;s2 = ' ' + s2; if(s1.size() < s2.size())swap(s1,s2); for(int i = 2, j = 0; i < s2.size(); ++i){ while(j > 0 && s2[i] != s2[j+1]) j = jump[j];//如果说不能匹配就跳回之前能匹配的位置 if(s2[i] == s2[j+1]) ++j;//否则j指针随i指针的右移而右移 jump[i] = j; }//求失配数组 for(int i = 1,j = 0; i < s1.size(); ++i){ while(j > 0 && (j == s2.size() || s1[i] != s2[j+1])) j = jump[j];//失配就调回该进行匹配的地方 if(s1[i] == s2[j+1]) ++j; if(j == s2.size()-1) printf("%d\n",i-s2.size()+2); }// for(int i = 1; i < s2.size(); ++i){ printf("%d ",jump[i]); } }
本文来自博客园,作者:ricky_lin,转载请注明原文链接:https://www.cnblogs.com/rickylin/p/17092035.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步