KMP扩展

it2024-04-19  10

参考https://www.luogu.org/problemnew/solution/P5410

题目描述

有两个字符串aa,bb,要求输出bb与aa的每一个后缀的最长公共前缀

输入格式

两行,分别为两个字符串aa,bb

输出格式

共两行

第一行有lenb个数,为b的next数组(特别地,next 0为lenb)

第二行有lena个数,即答案

输入输出样例

输入

aaaabaa aaaaa

输出

5 4 3 2 1 4 3 2 1 0 2 1

代码

#include <stdio.h> #include <string.h> #define max(a,b) a>b?a:b #define maxn 100010 char a[maxn],b[maxn]; int next[maxn],exnext[maxn]; int lena,lenb; void get_next() { next[0]=lenb; int j=0; while(j+1<lenb&&b[j+1]==b[j]) j++; next[1]=j; int p0=1; for(int i=2;i<lenb;i++) { if(i+next[i-p0]<next[p0]+p0) next[i]=next[i-p0]; else { int now=p0+next[p0]-i; now=max(now,0); while(now+i<lenb&&b[now]==b[now+i]) now++; next[i]=now; p0=i; } } } void solve() { int j=0; while(j<lena&&j<lenb&&a[j]==b[j]) j++; exnext[0]=j; int p0=0; for(int i=1;i<lena;i++) { if(i+next[i-p0]<exnext[p0]+p0) { exnext[i]=next[i-p0]; } else { int now=p0+exnext[p0]-i; now=max(now,0); while(now+i<lena&&now<lenb&&a[now+i]==b[now]) now++; exnext[i]=now; p0=i; } } } int main() { scanf("%s%s",a,b); lena=strlen(a),lenb=strlen(b); get_next(); solve(); for(int i=0;i<lenb;i++) printf("%d%c",next[i],i!=(lenb-1)?' ':'\n'); for(int i=0;i<lena;i++) printf("%d ",exnext[i]); }
最新回复(0)