题解 P3570 [POI2014]PRZ-Criminals
题意
额外提供一个LOJ的翻译
题目分析
我们考虑枚举每一个可能的相遇位置
因此题解分为以下两个部分:
Part 1:
如果有两个序列长度一样,那我们可以直接舍弃掉前一个序列,因为它的第一位下标比后一个小,且它们两在往后匹配的过程中遇到的情况始终是一样的。(上面例子的第2,3两个序列就是如此)
我们只需要知道每个序列第一个下标是多少,以及目前需要匹配
有了这两个想法,我们可以记
可是如果在这之前有序列要匹配第
附上代码:
for(int i=1;i<=m;i++)num[a[i]]=i;
pos[1]=1;//造一个空序列需要匹配第一位
int tot=1;
for(int i=1;i<=n;i++){
if(pos[num[c[i]]]){//存在一个序列需要匹配这一位
int x=num[c[i]];
if(x==1)H[pos[1]]=i;//记下出发点
pos[x+1]=pos[x];pos[x]=0;
if(x==1)pos[1]=++tot;//跟前面同理
}
L[i]=(pos[m+1]!=0&&c[i]==a[m])?H[pos[m+1]]:0;//如果有序列已经匹配完m位,L[i]即为那个序列的出发点。
}
//以下是求R[i]
memset(num,0,sizeof(num));memset(pos,0,sizeof(pos));memset(H,0,sizeof(H));
for(int i=1;i<=l;i++)num[b[i]]=i;
pos[1]=1;tot=1;
for(int i=n;i>=1;i--){
if(pos[num[c[i]]]){
int x=num[c[i]];
if(x==1)H[pos[1]]=i;
pos[x+1]=pos[x];pos[x]=0;
if(x==1)pos[1]=++tot;
}
R[i]=(pos[l+1]!=0&&c[i]==b[l])?H[pos[l+1]]:n+1;
}
时间复杂度:
Part 2:
对于每一种颜色
然后对于位置
附上代码:
for(int i=1;i<=n;i++)pos[c[i]]=i;
for(int i=1;i<=n;i++)pre[i]=max(pre[i-1],pos[c[i]]);
for(int i=1;i<=n;i++){
if(c[i]!=a[m])continue;
if(pre[L[i]-1]>R[i])ans.push_back(i);
}
时间复杂度: