扩展KMP (EX-KMP)

时间:2019-08-06
本文章向大家介绍扩展KMP (EX-KMP),主要包括扩展KMP (EX-KMP)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

next数组和extend数组

设有字符串S,T,next[i]表示T[i...len]与T[0..len]的最长公共前缀,extend[i]表示S[i...len]与T[0...len]的最长公共前缀,扩展kmp要做的就是把extend数组求出来.

思路

假设当前在匹配到s串的i位置,设p=i,然后开始比较while(S[p]==T[p-i]) p++,此条件一直满足直到p=p0时不成立,也就是说S[i....p-1]=T[0....p-1-i],此时记extend[i]=p-i,a=i.那么接下来i从i+1到p的过程中,只有以下三种情况:

(1)i+next[i-a]<p;

此时由于S[a...p-1]=T[0...p-1-a],有S[i...p-1]=T[i-a...p-a],而i+next[i-a]也不超出p-1等价于i-a+next[i-a]不超出p-1-a,所以有extend[i]=next[i-a].

(2)i+next[i-a]>=p;

此时i+next[i-a]已经超出p-1,而我们从a出发只能确定S[a...p-1]的字符信息,因此要以此时的i为起点重新开始最初的匹配过程,因为有S[i..p-1]=T[i-a..p-a],且i+next[i-a]>=p等价于i-a+next[i-a]>=p-a,也就是说从S[i...p-1]=T[0...p-1-a],因此不需要重新从i开始对比,只需要继续从上次的p开始对比S[p]==T[p-i]下去就行了,直接执行while(S[p]==T[p-i]) p++,更新操作和之前一样.

(3)i>=p;

如上所说我们只能确认S[a...p-1]的字符信息,因此在p字符之后只能重新开始比对--设p=i,然后开始执行while(S[p]==T[p-i]) p++,更新操作和之前一样.

以上方法可以同求next数组和extend数组,在求next数组时只需把上述s串也当成t串就行了.

代码

 1 string s,t;
 2 int next[MAX];
 3 int extend[MAX];
 4 
 5 void get_next(int n) 
 6 {
 7     next[0]=n;
 8     int a=0,p=0;
 9     for(int i=1;i<n;i++)
10     {
11         if(i+next[i-a]>=p)
12         {
13             if(i>=p) p=i;
14             while(p<n&&t[p]==t[p-i]) p++;
15             next[i]=p-i;
16             a=i;
17         }
18         else next[i]=next[i-a]; 
19     }
20 }
21 
22 void exkmp(int n,int m) //n为s串长度,m为t串长度 
23 {
24     get_next(m);
25     int a=0,p=0;
26     for(int i=0;i<n;i++)
27     {
28         if(i+next[i-a]>=p)
29         {
30             if(i>=p) p=i;
31             while(p<n&&p-i<m&&s[p]==t[p-i]) p++;
32             extend[i]=p-i;
33             a=i;
34         }
35         else extend[i]=next[i-a];
36     }
37 }

原文地址:https://www.cnblogs.com/VBEL/p/11308549.html