KMP算法的理解,伪代码,c代码实现

1、字符串问题形式化定义:假设文本是一个长度为n的T[1..n],而模式是一个长度为m的数组P[1..m],其中m<=n,如果有T[s+1..s+m]==P[1..m],那么就称模式P在T中出现。s为有效偏移,否则称为无效偏移。 2、方法:首先基于模式进行预处理,然后找到所有有效偏移(匹配)。
几种方法的预处理时间和匹配时间
朴素算法
    
    
    
    
    
    0
    
    
    
    
    
    O((n-m+1)*m)
Rabin-Karp
    
    
    
    
    
  O(m)
    
    
    
  
    
O((n-m+1)*m)
有限自动机算法
    
    
    
  
O(m|所有有限长度字符串的集合|)
    
    
 
 
O(n)  
KMP
    
    
    
    
    
    
    
   
O(m)
    
    
 
   
    
  O(n)
3、朴素字符串匹配算法:通过循环的方式找到所有有效偏移s。有效偏移s的可能有n-m+1个,每次匹配需要m次,因此共需匹配(n-m+1)*m次。
伪代码:
NAIVE-STRING-MATCHER(T,P)
1. n=T.length
2. m=P.length
3. for s=0 to n-m
4.
    
    if P[1..m] == T[s+1..s+m]
5.
    
    
    
    
 printf “Pattern occurs with shift” s
缺点:忽略了检测无效s值时获得的文本信息。
4、Rabin-Karp算法:初等数论的概念。暂且不研究。
5、利用有限自动机进行字符串匹配:首先建立好一个有限自动机,然后根据有限自动机进行匹配。
有限自动机:包括五个元素,所有状态的集合,初始状态,接收状态的集合,有限输入字母表,转移函数。
6、KMP算法:通过前缀函数避免对无用偏移进行检测。也可以避免在自动机匹配中,对整个转移函数的计算。主要原因在于字符串中存在部分匹配的现象。
本质:
针对待匹配的模式串的特点,判断它是否有重复的字符,从而找到它的前缀与后缀,进而求出相应的Next数组,最终根据Next数组而进行KMP匹配
next数组:记录下字符串P中的共有元素的位置,即第一个共有元素向后便宜多少可以到达第二个相同的元素哪儿。
“部分匹配”的实质是,有时候,字符串头部和尾部会有重复。比如,”ABCDAB”之中有两个”AB”,那么它的”部分匹配值”就是2(”AB”的长度)。搜索词移动的时候,第一个”AB”向后移动4位(字符串长度-部分匹配值),就可以来到第二个”AB”的位置。
大致思路:
kmp的比较函数:
1.首先初始化好NEXT数组, next[0]=0,next[1]=1
2.循环查找模式P是否在T中
    1)首先比较P[i] == T[j],如果相等,继续比较下一个,否则执行2.2)
    2)令j=next[j],继续比较(这一步避免了回溯)
    3)如果j==0; 表明没有匹配,则i++, j++
3.直到找到P在T中的位置或者T已经被比较晚结束。
当发生失配的情况下,j的新值next[j]取决于模式串中T[0 ~ j-1]中前缀和后缀相等部分的长度, 并且next[j]恰好等于这个最大长度
next数组的初始化
1.定义next数组, 令next[0]=0, next[1]=1
2.从p[2]开始循环计算对应的next数组
3.
    循环计算next[j]的值
4.
    
    从next[j]往前找到某个p[i]=p[next[i]],如果相等则next[j]=next[i]+1
5.
    
    否则,令i=next[i]继续向前查找,直到找到相等的为止。
6.
    
    
如果i=0,则表明模式P中没有p[j]相同的前缀,令next[j]=1
    
    

7、伪代码:
初始化NEXT数组
NEXT-FUNC(P, next)
1.let next[1..m] = -1
2.next[1]=0, next[2]=1
3.for i=3 to m
4.
    
 j = i
5.     while j != 0
5.
   
    
 
 
if P[j]
 == P[next[j]]
6.
    
    
    
   
next[i]=next[j]+1
7.
    
    
    
   break
;
8.
    
    
 
else
 
9.
    
    
    
   j = next[j]
10.
    if   j == 0 then next[j] = 1
 
    
KMP-CMP(T, P)    
1.
NEXT-FUNC(P, next), j = 0; 
2.for T[i] form T[0] to T[n]
3.
    if T[i]
 == S[j]  
4.
    
    if j == m  then retrun true 
5.
    
    
then i++ j++
6.
    
else j = next[j];
7.
    if j == 0 then i++ j++


8、c语言代码
#include int nextArr(char* p, int* next, int m){ next[1] = 0; next[2] = 1; int i, j; for(i=3; i j=i; while(j!=0){ if(p[j] == p[next[j]]){ next[i] == next[j]+1; break; }else{ j=next[j]; } } if(j==0) { next[j] = 1; } } return 0; } int kmpCMP(char* t, char* p, int n, int m){ int i = 0,j =0; int next[10]; next[0] = 0; nextArr(p, next, m); for(i=0; i if(t[i]==p[j]){ if(j==m-1){ printf(“%d\n”, i-m+2); return 1; }else{ j++; continue; } }else{ j=next[j]; } if(j==0){ j=1; } } return 0; } 







    
    
    







    原文作者:KMP算法
    原文地址: https://blog.csdn.net/jiangbianxiumu/article/details/38337655
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞