( 字符串专题 )【 扩展KMP 】
时间复杂度:O(n+m)
作用:在线性时间内计算 串T(长度为n)的每一个后缀对应 串P(长度为m)的最长公共前缀。
用 extend[i]表示T[i~n-1]与P的最长公共前缀。
假设T=“AAAAB”, P="AAAA"。则extend[5] = {4,3,2,1,0}
next[i]表示为 串P 中以 i 为起点的后缀字符串和 整个串P 的最长公共前缀长度.
假设P=“AAAAB” 则next[5] = {5,3,2,1,0}
模板
#include<bits/stdc++.h>
using namespace std;
//next[i]:x[i...m-1] 与 x[0...m-1] 的最长公共前缀
//extend[i]:y[i...n-1] 与 x[0...m-1] 的最长公共前缀
int nxt[200005],extend[200005];
char s[200005], t[200005];
void get_nxt()
{
int len = strlen(t);
nxt[0] = len;
int j = 0;
while ( j+1<len && t[j]==t[j+1] ) j++;
nxt[1] = j;
int k = 1;
for ( int i = 2; i<len; i++ ) {
int p = nxt[k]+k-1;
int L = nxt[i-k];
if( i+L < p+1 ) nxt[i] = L;
else {
j = max(0,p-i+1);
while( i+j<len && t[i+j]==t[j] ) j++;
nxt[i] = j;
k = i;
}
}
}
int exkmp()
{
int lens = strlen(s);
int lent = strlen(t);
get_nxt();
int j = 0;
while( j<lens && j<lent && t[j]==s[j] ) j++;
extend[0] = j;
int k = 0;
for( int i = 1; i<lens; i++ ) {
int p = extend[k]+k-1;
int L = nxt[i-k];
if( i+L<p+1 ) extend[i] = L;
else {
j = max(0,p-i+1);
while( i+j<lens && j<lent && s[i+j]==t[j] ) j++;
extend[i] = j;
k = i;
}
}
}
int main()
{
cin>>s;
cin>>t;
exkmp();
for ( int i=0; i<strlen(s); i++ ) cout << extend[i] << " ";
return 0;
}