KMP算法
来源:互联网 发布:南京行知基地卫生间 编辑:程序博客网 时间:2024/05/11 12:13
字符串比较,是实际应用中比较重要的一个内容,如果单纯的逐位比较,显然是太慢了(当然,朴素的字符串比较算法在平均情况下表现还是很好的)。下面要介绍的是KMP算法。
思想
KMP算法的思想很简单,它最核心的思想就是当失配时利用当前的信息而不是重新从头比较。考虑A串和B串,要求B在A第一次出现的位置(通常称B串为模式串)。令p[i]表示小于i的最大的x,使得[1,x]=[i-x+1,i](如何求p数组的问题等下再探讨)。那么,如果失配(A[i]≠B[j]),在这种情况下,朴素算法将令j=1,重新比较,但是,KMP算法利用了已经处理过的信息,即
int j=0;for(int i=1;i<=n;i++){ while(j&&s1[i]!=s2[j+1])j=p[j]; if(cmp(s2[j+1],s1[i]))j++; if(j==m){ printf("%d",i-m+1); return 0; }}
如何求p数组
要求p[i]我们可以利用p[1..i-1],我们知道,p[i]表示的是使前缀等于后缀的最大长度,所以,最好的情况一定是
p[1]=0;for(int i=2;i<=m;i++){ int j=p[i-1]; while(j&&!cmp(s2[j+1],s2[i]))j=p[j]; if(cmp(s2[j+1],s2[i]))p[i]=j+1;}
有没有发现,这段求P数组的代码和上面的比较的代码惊人的相似。这是因为,求P数组实际上就是一个对模式串进行自我匹配的过程。
时间复杂度
KMP的时间复杂度是线性的,即是
代码如下:
#include<cstdio>#include<cstring>#include<algorithm>#define maxn 100006using namespace std;inline char nc(){ static char buf[100000],*i=buf,*j=buf; return i==j&&(j=(i=buf)+fread(buf,1,100000,stdin),i==j)?EOF:*i++;}inline int read_s(char *x){ char ch=nc();int len=0; while(ch!='\n'&&ch!=EOF)*x++=ch,len++,ch=nc(); *x='\0'; return len;}int n,m,p[maxn];char s1[maxn],s2[maxn];int main(){ freopen("str.in","r",stdin); freopen("str.out","w",stdout); n=read_s(s1+1);m=read_s(s2+1); p[1]=0; for(int i=2;i<=m;i++){ int j=p[i-1]; while(j&&s2[j+1]!=s2[i])j=p[j]; if(s2[j+1]==s2[i])p[i]=j+1; } int j=0; for(int i=1;i<=n;i++){ while(j&&s2[j+1]!=s1[i])j=p[j]; if(s2[j+1]==s1[i])j++; if(j==m){ printf("%d",i-m+1); return 0; } } printf("-1"); return 0;}
- KMP算法详解 【KMP】
- 【KMP】KMP算法模板
- KMP hihoCoder1015 KMP算法
- kmp算法
- KMP算法
- KMP算法
- KMP算法
- KMP算法
- KMP 算法
- kmp算法
- KMP算法
- kmp算法
- KMP算法
- KMP算法
- kmp算法
- kmp算法
- KMP算法
- KMP算法
- Hive原理
- Python UnicodeEncodeError: 'gbk' codec can't encode character 解决方法
- IT专业英语整理积累(1)
- Android Studio在创建项目是一直处于building “project name”gradle project info的解决办法
- CSS、JS中的相对路径引用
- KMP算法
- PHP面试总结-2
- 欧拉公式的推导
- AS意外死机后,全屏红线
- 测试基础
- 影像组学学习笔记
- BIRCH聚类算法原理
- 字符指针动态创建字符串在使用时并不能完全取代字符数组
- Socket网络程序设计(1) ———— 基于TCP协议的客户-服务器socket实例