扩展KMP可以快速求出T与S每个后缀的LCP,时间复杂度和空间复杂度都比后缀数组要优良很多。
const LL N = 200005; //扩展KMP int nex[N];//T串的每一个后缀与T的LCP int ext[N]; char S[N]; char T[N]; void getNex() { //int len = T.length(); int len = strlen(T); nex[0] = len; int i=0, j=0,po=1; while (i + 1 < len&&T[i] == T[i + 1])i++; nex[1] = i; for (i = 2; i < len; i++) { int P = nex[po] + po; if (i + nex[i - po] < P)//(T均为T的后缀)因为T[po]和T[0]匹配,所以T[i]和T[i-po]匹配,那么只要知道nex[i-po],计算最远长度是否超过P nex[i] = nex[i - po]; else { j = P - i;//nex[i-po]>P-i,所以从P-i往后都是未知的,需要匹配. if (j < 0)j = 0;//如果po也没有lcp就会出现负数,就0开始匹配 while (i + j<len&&T[i + j] == T[j])j++; nex[i] = j; po = i;//这里if可以不需要,因为如果P不够匹配了,新的j必然>=P } } } void exKmp() { getNex(); //int lens = S.length(); //int lent = T.length(); int lens = strlen(S); int lent = strlen(T); int i=0, j=0, po=0; while (i+j<lens&&j<lent&&S[i + j] == T[j])j++; ext[i] = j; po = 0; for (i = 1; i < lent; i++) { int P = ext[po] + po; if (i + nex[i - po] < P) ext[i] = nex[i - po];//此处用nex而不是ext的原因是,需要通过T串后缀的lcp找到尽可能匹配的长度 else { j = P - i; if (j < 0)j = 0; while (i + j<lens&&j<lent&&S[i + j] == T[j])j++; ext[i] = j; po = j; } } }