题解 P8112 【[Cnoi2021]符文破译】(Z 函数,单调队列优化 dp)

场上的小丑做法不请自来。

开题:SAM 的萌萌题?这数据范围的不对劲啊。哦,Z 函数就能做了,我降智了。(此时还没意识到自己还是降智了)


problem

给定字符串 ST,要求将 S 划分成最少的段,且每段是 T 的前缀。(1|S||T|107


solution

正着不好做,考虑倒着 dp,limi 表示 S[i,n]T 的最长公共前缀,设 fi 表示 S[i,n] 最少的划分,则转移方程为:fi=mini<ji+limi{fj}+1

lim 可以用 Z-box 求,然后 O(n2)O(nlogn) 做法就显然了,但是这题要求线性。

分析一下,若:i<ii+limi>i+limi,那么从 i 进行划分一定不优,这里的 i 可以直接不用考虑。

把上述的位置扔掉后,i+limi 就是单调的了,可以使用单调队列进行优化,时间复杂度 O(n)

比 kmp 更优美。


code

#include<bits/stdc++.h> using namespace std; #define rg register #define ll long long #define ull unsigned ll #define inf 0x3f3f3f3f #define djq 998244353 #define lowbit(x) (x&(-x)) inline void file(){ freopen("baka.in","r",stdin); freopen("baka.out","w",stdout); } char buf[1<<21],*p1=buf,*p2=buf; inline int getc(){ return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++; } inline int read(){ rg int ret=0,f=0;char ch=getc(); while(!isdigit(ch)){if(ch==EOF)exit(0);if(ch=='-')f=1;ch=getc();} while(isdigit(ch)){ret=ret*10+ch-48;ch=getc();} return f?-ret:ret; } int n,m,lim[10000005],z[10000005],f[10000005];; char s[10000005],t[10000005]; int q[10000005],fr,re; signed main(){ //file(); scanf("%d%d%s%s",&m,&n,t+1,s+1); z[1]=m; for(rg int i=2,l=0,r=0;i<=m;++i){ if(i<=r) z[i]=min(r-i+1,z[i-l+1]); else z[i]=0; while(i+z[i]<=m&&t[1+z[i]]==t[i+z[i]]) ++z[i]; if(r<i+z[i]-1) l=i,r=i+z[i]-1; } for(rg int i=1,l=0,r=0;i<=n;++i){ if(i<=r) lim[i]=min(r-i+1,z[i-l+1]); else lim[i]=0; while(i+lim[i]<=n&&1+lim[i]<=m&&t[1+lim[i]]==s[i+lim[i]]) ++lim[i]; if(r<i+lim[i]-1) l=i,r=i+lim[i]-1; } for(rg int i=1,j=0;i<=n;++i) j>i+lim[i]?lim[i]=inf:j=i+lim[i]; memset(f,0x3f,sizeof(f)); f[n+1]=0; q[fr=re=1]=n+1; for(rg int i=n;i>=1;--i){ if(lim[i]==inf) continue; while(fr-1!=re&&q[fr]>i+lim[i]) ++fr; const int j=q[fr]; f[i]=f[j]+1; while(fr-1!=re&&f[q[re]]>=f[i]) --re; q[++re]=i; } if(f[1]>=0x3f3f3f3f) puts("Fake"); else printf("%d",f[1]); return 0; } /* */

__EOF__

本文作者Legitimity
本文链接https://www.cnblogs.com/tiatto/p/15875707.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Legitimity  阅读(80)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示