P6080-Cow Patterns G
前言
我看题解中一个是用的 Z 函数,另一个是 set,所以决定将链表解法分享出来。
这道题的思路与 P4696 差不多,都是记录前驱与后继。
解法
在这道题目中,我们只需要记录出模式串的大小关系,使用树状数组显然处理具有相等关系时更具有优势,但是本题解想另寻思路,利用链表的形式储存。
我们发现
然后就对于模式串算出
bool check1(int n1,int n2)
{
bool flag=true;
if(les[n1])
{
int xi=n2-(n1-les[n1]);
if(val[les[n1]]==val[n1])
{
if(val[xi]!=val[n2])flag=false;
}
else
{
if(val[xi]>=val[n2])flag=false;
}
}
if(mor[n1])
{
int xi=n2-(n1-mor[n1]);
if(val[mor[n1]]==val[n1])
{
if(val[xi]!=val[n2])flag=false;
}
else
{
if(val[xi]<=val[n2])flag=false;
}
}
return flag;
}
bool check2(int n1,int n2)
{
bool flag=true;
if(les[n1])
{
int xi=n2-(n1-les[n1]);
if(val[les[n1]]==val[n1])
{
if(h[xi]!=h[n2])flag=false;
}
else
{
if(h[xi]>=h[n2])flag=false;
}
}
if(mor[n1])
{
int xi=n2-(n1-mor[n1]);
if(val[mor[n1]]==val[n1])
{
if(h[xi]!=h[n2])flag=false;
}
else
{
if(h[xi]<=h[n2])flag=false;
}
}
return flag;
}
整体代码如下:
#include<iostream>
#include<iomanip>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
int n,m,S;
int p[1000001],h[1000001];
int pos[1000001],val[1000001];
int les[1000001],mor[1000001];
int nex[1000001];
int ans,ge[1000001];
struct Node
{
int val,pos,ls;
int next,prev;
}node[1000001];
bool check1(int n1,int n2)
{
bool flag=true;
if(les[n1])
{
int xi=n2-(n1-les[n1]);
if(val[les[n1]]==val[n1])
{
if(val[xi]!=val[n2])flag=false;
}
else
{
if(val[xi]>=val[n2])flag=false;
}
}
if(mor[n1])
{
int xi=n2-(n1-mor[n1]);
if(val[mor[n1]]==val[n1])
{
if(val[xi]!=val[n2])flag=false;
}
else
{
if(val[xi]<=val[n2])flag=false;
}
}
return flag;
}
bool check2(int n1,int n2)
{
bool flag=true;
if(les[n1])
{
int xi=n2-(n1-les[n1]);
if(val[les[n1]]==val[n1])
{
if(h[xi]!=h[n2])flag=false;
}
else
{
if(h[xi]>=h[n2])flag=false;
}
}
if(mor[n1])
{
int xi=n2-(n1-mor[n1]);
if(val[mor[n1]]==val[n1])
{
if(h[xi]!=h[n2])flag=false;
}
else
{
if(h[xi]<=h[n2])flag=false;
}
}
return flag;
}
bool cmp(Node a,Node b)
{
if(a.val==b.val)return a.pos<b.pos;
return a.val<b.val;
}
bool tmp(Node a,Node b)
{
return a.pos<b.pos;
}
void pre()
{
for(int i=1;i<=n;i++)
{
node[i].val=val[i];
node[i].pos=i;
}
sort(node+1,node+n+1,cmp);
int g=0;
for(int i=1;i<=n;i++)
{
if(i==1||node[i].val>node[i-1].val)g++;
node[i].ls=g;
}
for(int i=1;i<=n;i++)
{
node[i].prev=node[i-1].pos;
node[i].next=node[i+1].pos;
}
node[1].prev=0;
node[n].next=0;
sort(node+1,node+n+1,tmp);
}
int main()
{
scanf("%d%d%d",&m,&n,&S);
for(int i=1;i<=m;i++)scanf("%d",&h[i]);
for(int i=1;i<=n;i++)scanf("%d",&val[i]);
for(int i=1;i<=n;i++)pos[val[i]]=i;
pre();
for(int i=n;i>=1;i--)
{
les[i]=node[i].prev;
mor[i]=node[i].next;
node[node[i].next].prev=node[i].prev;
node[node[i].prev].next=node[i].next;
}
for(int i=2;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++;
nex[i]=j;
}
// for(int i=1;i<=n;i++)cout<<nex[i]<<" ";
// cout<<endl;
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\n",ge[i]);
return 0;
}