题目链接:https://www.luogu.org/problem/P5410
题意:给两个字符串a,b,求b对a的每一个后缀的最大前缀长度
分析:扩展KMP(又称Z-algorithm算法)裸题
该博客讲解的比较好:https://www.luogu.org/blog/lc-2018-Canton/solution-p5410
但他有几个地方讲的有几个问题,主要在情况2里面
首先是一开始S[K+L]肯定是在p的后面,这个比较明显
然后情况二红蓝绿三条线的序列不是一样的,红绿还是一样的,但是蓝线就不等了,这个自己看一看
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e5+7;//单词间自行添加了符号,稍做扩大 const ll inf=1e18; #define meminf(a) memset(a,0x3f,sizeof(a)) #define mem0(a) memset(a,0,sizeof(a)); char a[maxn],b[maxn]; int nxt[maxn],extend[maxn];//nxt[i]代表b[i...len]和b的最大前缀长度,extend[i]代表a[i...len]和b的最大前缀长度 void getnxt(){ int len=strlen(b); nxt[0]=len;//nxt[0]就是原串情况下,自然就为len int now=0; while(b[now]==b[now+1]&&now+1<len) now++; nxt[1]=now; int p0=1;//p0是满足p0+nxt[p0]-1最大的点,一开始初始化为1 for(int i=2;i<len;i++){ if(i+nxt[i-p0]<p0+nxt[p0]) nxt[i]=nxt[i-p0]; //i相当于k+1,nxt[i-p0]相当于L(nxt[k-p0+2) 这里字符串是从0开始的,和博客里面从1开始的区别是少加一个1 else{ int now=p0+nxt[p0]-i; now=max(now,0);//防止i在p的后面 while(b[now]==b[i+now]&&i+now<len) now++; nxt[i]=now; p0=i;//更新p0 } } } void exkmp(){ getnxt(); int len=strlen(a); int now=0; while(a[now]==b[now]&&now<min(strlen(a),strlen(b))) now++; extend[0]=now; int p0=0; for(int i=1;i<len;i++){ if(i+nxt[i-p0]<extend[p0]+p0) extend[i]=nxt[i-p0]; else{ int now=p0+extend[p0]-i; now=max(now,0); while(b[now]==a[i+now]&&now<strlen(b)&&i+now<len) now++; extend[i]=now; p0=i; } } } int main(){ scanf("%s%s",a,b); exkmp(); for(int i=0;i<strlen(b);i++) printf("%d ",nxt[i]); putchar(' '); for(int i=0;i<strlen(a);i++) printf("%d ",extend[i]); putchar(' '); return 0; }