【题解】P4696 [CEOI2011] Matching

原题链接


题目描述

对于整数序列 (a1,a2,,an)1n 的排列 (p1,p2,,pn),称 (a1,a2,,an) 符合 (p1,p2,,pn),当且仅当:

  • {a} 中任意两个数字互不相同;

  • (a1,a2,,an) 从小到大排序后,将会得到 (ap1,ap2,,apn)

现在给出 1n 的排列 {p} 和序列 h1,h2,,hm​​,请你求出哪些 {h} 的子串符合排列 {p}

题解

人类智慧题,解法是不容易想到的。
nlogn的线段树hash,然而有更优秀的 O(n) kmp。
考虑重新定义kmp的相等,我们记录比当前数小的最大的数(前驱)和大的最小的数(后继),如果所有的数都满足相对位置前驱处的数比它小且后继处的数比它大那么当前序列是满足的。
重写下比较函数就行。

#include<bits/stdc++.h>
using namespace std;
inline int rd(){
	int f=1,j=0;
	char w=getchar();
	while(!isdigit(w)){
		if(w=='-')f=-1;
		w=getchar();
	}
	while(isdigit(w)){
		j=j*10+w-'0';
		w=getchar();
	}
	return f*j;
}
const int N=1000010;
int n,m;
int p[N],h[N];
int pos[N],val[N];
int les[N],mor[N];
int nex[N];
int ans,ge[N];
struct Node
{
	int next,prev;
}node[N];
bool check1(int n1,int n2)
{
	bool flag=true;
	if(les[n1]&&val[n2-(n1-les[n1])]>=val[n2])flag=false;
	if(mor[n1]&&val[n2-(n1-mor[n1])]<=val[n2])flag=false;
	return flag;
}
bool check2(int n1,int n2)
{
	bool flag=true;
	if(les[n1]&&h[n2-(n1-les[n1])]>=h[n2])flag=false;
	if(mor[n1]&&h[n2-(n1-mor[n1])]<=h[n2])flag=false;
	return flag;
}
int main()
{
	n=rd(),m=rd();
	for(int i=1;i<=n;i++)
	{
		p[i]=rd();
		val[p[i]]=i;
	}
	for(int i=1;i<=m;i++)h[i]=rd();
	for(int i=1;i<=n;i++)pos[i]=p[i];
	for(int i=1;i<=n;i++)node[i].next=i+1,node[i].prev=i-1;
	for(int i=n;i>=1;i--)
	{
		les[i]=pos[node[val[i]].prev];
		mor[i]=pos[node[val[i]].next];
		node[node[val[i]].next].prev=node[val[i]].prev;
		node[node[val[i]].prev].next=node[val[i]].next;
	}
	for(int i=1;i<=n;i++)
	{
		int j=nex[i-1];
		while(j>0&&check1(j+1,i)==false)j=nex[j];
		if(check1(j+1,i)==true&&j+1<i)j++;
		nex[i]=j;
	}
	int j=0;
	for(int i=1;i<=m;i++)
	{
		while(j>0&&check2(j+1,i)==false)j=nex[j];
		if(check2(j+1,i)==true)j++;
		if(j==n)
		{
			j=nex[j];
			ge[++ans]=i-n+1;
		}
	}
	cout<<ans<<endl;
	for(int i=1;i<=ans;i++)printf("%d ",ge[i]);
	return 0;
}

代码不想写了喵

posted @   flywatre  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示