“一切都会好起来的。”|

zplqwq

园龄:3年10个月粉丝:25关注:14

2022-06-21 17:30阅读: 52评论: 0推荐: 0

题解 P4696 [CEOI2011]Matching

这道题挺妙的。

首先我们需要一个数组 a,存的是转化后的 p 数组。例如,我们将序列 2,1,5,3,4 转化为 2,1,4,5,3 ,分别对应的是 h 数组中的 6,3,8,1,2,7

实现如下:

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 中国大陆许可协议进行许可。

posted @   zplqwq  阅读(52)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起