题解 P4696 [CEOI2011]Matching
这道题挺妙的。
首先我们需要一个数组 ,存的是转化后的 数组。例如,我们将序列 转化为 ,分别对应的是 数组中的 。
实现如下:
for(int i=1;i<=n;i++) { p[i]=read(); a[p[i]]=i; pre[i]=i-1; net[i]=i+1; }
然后我们维护一个双向链表,用它来求比序列中的某个数大的最小位置和比它小的最大位置。那么,为什么呢?
因为我们考虑一个序列是否合法,不用枚举整个。只需要判断每一个数是否比它前一个位置大,后一个位置小。即大于它的前驱,小于它的后继。
之后就是一个类似 kmp 的思路。
在 kmp 的板子中,我们比对的是子串与要匹配的串是否相同。而现在我们判断的是该子串是否合法。
其余与 kmp 基本一致。
int j=0; for(int i=2;i<=n;i++) { while(j>0 and !check(a,j+1,i)) j=kmp[j]; if(check(a,j+1,i)) j++; kmp[i]=j; } j=0; for(int i=1;i<=m;i++) { while(j>0 and !check(h,j+1,i)) j=kmp[j]; if(check(h,j+1,i)) j++; if(j==n) { qwq[++ans]=i-n+1; j=kmp[j]; } }
其余请自行实现。如果有问题,可以私信我要完整代码。
本文作者:zplqwq
本文链接:https://www.cnblogs.com/zplqwq/p/16397657.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步