Luogu P5410【模板】扩展 KMP
题意:求 \(T\) 与 \(S\) 的每个后缀的最长公共前缀。
先令 \(s=S+T\) ,\(z[i]\) 表示 \(T\) 与 \(suff_i\) 的最长公共前缀。
(注意下标是从 \(0\) 开始的)
\(z[i]=min(z[i-l],r-i+1)\) ,前一部分如图:
后一部分是要保证不能越过最靠右的边界,因为更靠右的部分无法判断是否相等。
#include<iostream>
#include<cstdio>
#include<cstring>
#define R register int
using namespace std;
namespace Luitaryi {
const int N=100010;
int n,m,z[N<<1];
char s[N<<1],t[N];
inline void main() {
scanf("%s",t);
scanf("%s",s),n=strlen(s);
s[n]='#',memcpy(s+n+1,t,strlen(t));
for(R i=1,l=0,r;s[i];++i) {
if(i<=r) z[i]=min(z[i-l],r-i+1);
while(s[z[i]]==s[i+z[i]]) ++z[i];
if(i+z[i]-1>r) r=i+z[i]-1,l=i;
} printf("%d ",n);
for(R i=1;i<n;++i) printf("%d ",z[i]);
puts("");
for(R i=n+1;s[i];++i) printf("%d ",z[i]);
}
} signed main() {Luitaryi::main(); return 0;}
2019.01.09