标签:style blog http io color ar sp for div
给定串S和T,求S的每一个后缀和T的最长公共前缀。
方法1:暴力算法,时间复杂度O(n^2);
方法2:后缀数组,利用height的性质可以求出该问题,时间复杂度为O(n),但是预处理为O(nlogn)
方法3:扩展KMP,充分利用已经匹配过的性质,降低匹配的时间,时间复杂度为O(n)
学习资料:http://www.docin.com/p-423302546.html
设next[i]为这样一个数组,next[i]为串T的suffix(i)和suffix(0)的相似度,假设next[0-->k-1]已经算出了,并且在以前的匹配中,
匹配到的最远处为p,如图
假设是suffix(a)和suffix(0)匹配到最远处p,那么有T[a-->p] == T[0-->p-a+1]那么这个匹配的后面一段也相等,即T[k-->p]==T[k-a-->p-a+1],
又因为next[k-a]是已知的,令L = next[k-a]
有两种情况,
①k+L-1 < p, 那么next[k] = L,不可能大于L,否则next[k-a] 就不等于L了, 可能有人会想到,为什么表示k+L-1<=p,这个因为,如果取等号,那么p+1的部分没被判断过,所以不能直接next[k] = L;
②K+L-1>=p, 那么要重新匹配超过p的部分,即T[p+1] 和T[p-k+1]重新匹配。
九度oj 1535
1 /*next[i] 表示T[i-->n]和T[0-->n]的相似度 2 */ 3 4 #include <stdio.h> 5 #include <string.h> 6 const int N = 1000000 + 10; 7 char S[N],T[N]; 8 int next[N]; 9 int extend[N]; 10 void makeNext() 11 { 12 int n,a,j,k,L,p; 13 next[0] = n = strlen(T); 14 a = 0; 15 while(a+1<n && T[a]==T[a+1]) a++; 16 next[1] = a; 17 a = 1; 18 for(k=2; k<n; ++k) 19 { 20 p = a + next[a] - 1; 21 L = next[k-a]; 22 if(k+L-1>=p) 23 { 24 //这一切都要求p>=k,否则,从新从0开始匹配。 25 j = p - k + 1 > 0 ? p-k+1 : 0; 26 while(k+j<n && T[k+j]==T[j]) ++j; 27 next[k] = j; 28 a = k; 29 } 30 else 31 next[k] = L; 32 33 } 34 35 } 36 void makeExtend() 37 { 38 int sLen = strlen(S),tLen = strlen(T); 39 int len = sLen < tLen ? sLen : tLen; 40 int a = 0,k,j,L,p; 41 while(a<len && S[a]==T[a]) a++; 42 extend[0] = a; 43 a = 0; 44 for(k=1; k<sLen; ++k) 45 { 46 p = a + extend[a] -1; 47 L = next[k-a]; 48 if(k+L-1>=p) 49 { 50 j = p-k+1>0?p-k+1:0; 51 while(k+j<sLen&&j<tLen &&S[k+j]==T[j]) 52 j++; 53 extend[k] = j; 54 a = k; 55 } 56 else 57 extend[k] = L; 58 } 59 } 60 int main() 61 { 62 while(scanf("%s%s",S,T)!=EOF) 63 { 64 makeNext(); 65 makeExtend(); 66 int n = strlen(S); 67 int ans = 0; 68 for(int i=0; i<n; ++i) 69 if(extend[i] == n - i) 70 { 71 ans = extend[i]; 72 break; 73 } 74 printf("%d\n",ans); 75 } 76 return 0; 77 }
标签:style blog http io color ar sp for div
原文地址:http://www.cnblogs.com/justPassBy/p/4089619.html