KMP算法

Posted huzhaoyang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了KMP算法相关的知识,希望对你有一定的参考价值。

KMP算法

KMP算法的简介

  KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,简称KMP算法。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息,该算法时间复杂度为O(m+n)。

KMP算法的思路

  例题:http://hihocoder.com/problemset/problem/1015 

技术分享图片
 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 int n,l1,l2,j,ans;
 5 char s1[1000001],s2[1000001];
 6 int main()
 7 {
 8     scanf("%d",&n);
 9     while (n--)
10     {
11         scanf("%s%s",s2,s1);
12         l1=strlen(s1);
13         l2=strlen(s2);
14         ans=0;
15         for (int i=0;i<=l1-l2;i++)
16             for (int j=0;j<l2;j++)
17                 if (s1[i+j]!=s2[j])break;    
18                 else
19                     if (j==l2-1)ans++; 
20         printf("%d\\n",ans);
21     }
22 }
View Code

  对于这个程序,显然是无法通过的,所以我们要对这个程序进行优化!模拟过程,我们可以发现一个浪费时间的地方:技术分享图片技术分享图片

  其中大写字母表示一段字符串,小写字母表示字符,此图中A为0-i最长相同前后缀,即不存在一个大于等于len(A)的k使得s2[0..k]==s2[i-k+1..i],我们设这个next[i]表示从0到i-1的相同前后缀的长度,这是需要与处理的。可以证明A必然可以如图2跳到该位置,具体证明详见后面。

KMP算法的过程

  用i表示母串中匹配到第i个位置,子串中匹配到第j个位置,若s1[i]==s2[j]或j为0,i++,j++;反之则令j=next[j],继续进行判断(解释一下:相同显然要继续往下匹配,j就变成next[j],相当于做了后移操作)。

KMP算法预处理

  KMP算法需要预处理next数组,暴力预处理时间复杂度需要n^2,显然不行。所以我们算next[i]要利用前面的next[j],所以我们假设前面的next都已经算好了,则若s[i-1]==s[next[i-1]],next[i]=next[i-1]+1;不同若s[i-1]==s[next[next[i-1]]],则next[i]=next[next[i-1]]+1;不同若s[i-1]==s[next[next[next[i-1]]]]……直到求出next[i]或者变成了0。

KMP算法的程序

技术分享图片
 1 #include<cstdio>
 2 int n,l1,l2,ans,nex[10001];
 3 char s1[1000001],s2[10001];
 4 int calc(char *s,int k,char c)
 5 {
 6     for (;(k)&&(c!=s[k]);k=nex[k]);
 7     return k+=(s[k]==c);
 8 }
 9 char seek(char *s)
10 {
11     nex[0]=nex[1]=0;
12     for (int i=1,j=0;s[i];i++)nex[i+1]=j=calc(s,j,s[i]);
13 }
14 void kmp(char *s1,char *s2)
15 {
16     for (int i=0,j=0;s1[i];i++)
17         if (!s2[j=calc(s2,j,s1[i])])
18         {
19             ans++;
20             j=nex[j];
21         }
22 }
23 int main()
24 {
25     scanf("%d",&n);
26     while (n--)
27     {
28         scanf("%s%s",s2,s1);
29         seek(s2);
30         ans=0;
31         kmp(s1,s2);
32         printf("%d\\n",ans);
33     }
34 }
View Code

以上是关于KMP算法的主要内容,如果未能解决你的问题,请参考以下文章

数据结构—串KMP模式匹配算法

Python ---- KMP(博文推荐+代码)

KMP算法及Python代码

KMP算法及Python代码

图解KMP算法原理及其代码分析

Kmp算法Java代码实现