标签:soft 执行 sans 比较 思路 ping 扩展kmp 开始 string
设有字符串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的过程中,只有以下三种情况:
此时由于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].
此时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++,更新操作和之前一样.
如上所说我们只能确认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 }
标签:soft 执行 sans 比较 思路 ping 扩展kmp 开始 string
原文地址:https://www.cnblogs.com/VBEL/p/11308549.html