wenbao与扩展kmp

给定两个字符串S和T(长度分别为n和m),下标从0开始,定义extend[i]等于S[i]...S[n-1]与T的最长公共前缀的长度,求出所有的extend[i]

next[i]: T[i]...T[m-1]与T的最长公共前缀长度;
extend[i]: S[i]...S[n-1]与T的最长公共前缀的长度。

推荐博客:https://wenku.baidu.com/view/8e9ebefb0242a8956bece4b3.html

 1 //C/C++ 模板
 2 #include <iostream>
 3 #include <stdio.h>
 4 #include <string.h>
 5 using namespace std;
 6 const int N = 101010;
 7 int next[N],extand[N];
 8 void getnext(char *T){// next[i]: 以第i位置开始的子串 与 T的公共前缀 
 9     int i,length = strlen(T);
10     next[0] = length;
11     for(i = 0;i<length-1 && T[i]==T[i+1]; i++); //单独处理next[1]
12     next[1] = i;
13     int a = 1;
14     for(int k = 2; k < length; k++){
15         int p = a+next[a]-1, L = next[k-a];
16         if( (k-1)+L >= p ){
17             int j = (p-k+1)>0? (p-k+1) : 0; 
18             while(k+j<length && T[k+j]==T[j]) j++;// 枚举(p+1,length) 与(p-k+1,length) 区间比较 
19             next[k] = j, a = k;
20         } 
21         else next[k] = L;
22     } 
23 }
24 void getextand(char *S,char *T){
25     memset(next,0,sizeof(next)); 
26     getnext(T); 
27     int Slen = strlen(S), Tlen = strlen(T), a = 0;
28     int MinLen = Slen>Tlen?Tlen:Slen;
29     while(a<MinLen && S[a]==T[a]) a++;
30     extand[0] = a, a = 0;
31     for(int k = 1; k < Slen; k++){
32         int p = a+extand[a]-1, L = next[k-a];  
33         if( (k-1)+L >= p ){
34             int j = (p-k+1)>0? (p-k+1) : 0; 
35             while(k+j<Slen && j<Tlen && S[k+j]==T[j] ) j++; 
36             extand[k] = j;a = k; 
37         } 
38         else extand[k] = L;         
39     }
40 }
41 
42 int main(){
43     char s[N],t[N];
44     while(~scanf("%s %s",s,t)){
45         getextand(s,t); 
46         for(int i = 0; i < strlen(t); i++) printf("%d ",next[i]);
47         puts(""); 
48         for(int i = 0; i < strlen(s); i++) printf("%d ",extand[i]);
49         puts("");
50     } 
51 }
52 
53 /*
54 abababab abab
55 aaaabaaa aaaa
56 */

只有不断学习才能进步!

原文地址:https://www.cnblogs.com/wenbao/p/7146013.html