题目描述

给出两个长度分别为n、m的序列A、B,求出B的所有长度为n的连续子序列(子串),满足:序列中第i小的数在序列的Ai位置。

输入

第一行包含两个整数n, m (2≤n≤m≤1000000)。 
第二行包含n个整数si,构成1,2,…,n的排列,1≤si≤n且si≠sj。 
第三行包含m个整数hi,表示建筑的高度(1≤hi≤109,1≤i≤m),所有的hi均不相同。 
每一行的整数之间用单个空格隔开。

输出

第一行包含1个整数k ,表示匹配的序列数目。
第二行包含k个整数,分别为在正确匹配的每个序列中与标志编号1 的条纹相对应的第1 栋建筑的编号。这些数字按升序排列,用空格隔开。如果k=0 ,第二行为空行。

样例输入

5 10
2 1 5 3 4
5 6 3 8 12 7 1 10 11 9

样例输出

2
2 6


题解

特殊匹配条件的KMP+树状数组

考虑:序列满足条件可以由 每个数前面比它小的数的个数 判定。

于是我们可以先预处理出每个数前面比它小的数应该有多少个。

然后如果暴力匹配的话肯定会TLE,于是想到KMP算法。

所以需要先求出next数组。

考虑KMP求next数组的过程:当满足条件时从前一个递推到后一个。那么可以使用树状数组维护比一个数小的数的个数,当当前小于该数的数的个数不等于应有的个数时就减少长度,并暴力将减掉的数从树状数组中删除。

由于每次next减少对应的是前面的next的增加,而next每次只增加1,因此对于每个字符的均摊时间复杂度是$O(\log m)$的。

然后求出next数组后就是匹配的过程,和求next类似,需要离散化。

因此总的时间复杂度为$O((n+m)\log m)$。貌似本题还有线性做法,然而不会= =

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 1000010
int m , a[N] , s[N] , v[N] , h[N] , t[N] , next[N] , f[N] , sta[N] , tot;
inline void add(int x , int a)
{
int i;
for(i = x ; i <= m ; i += i & -i) f[i] += a;
}
inline int query(int x)
{
int i , ans = 0;
for(i = x ; i ; i -= i & -i) ans += f[i];
return ans;
}
int main()
{
int n , i , j , p = 0;
scanf("%d%d" , &n , &m);
for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]) , s[a[i]] = i;
for(i = 1 ; i <= n ; i ++ ) v[i] = query(s[i]) , add(s[i] , 1);
for(i = 1 ; i <= m ; i ++ ) scanf("%d" , &h[i]) , t[i] = h[i];
memset(f , 0 , sizeof(f));
for(i = 2 ; i <= n ; i ++ )
{
while(query(s[i]) != v[p + 1])
{
for(j = i - p ; j < i - next[p] ; j ++ ) add(s[j] , -1);
p = next[p];
}
next[i] = ++p , add(s[i] , 1);
}
sort(t + 1 , t + m + 1);
memset(f , 0 , sizeof(f));
p = 0;
for(i = 1 ; i <= m ; i ++ )
{
h[i] = lower_bound(t + 1 , t + m + 1 , h[i]) - t;
while(p == n || query(h[i]) != v[p + 1])
{
for(j = i - p ; j < i - next[p] ; j ++ ) add(h[j] , -1);
p = next[p];
}
p ++ , add(h[i] , 1);
if(p == n) sta[++tot] = i - n + 1;
}
printf("%d\n" , tot);
for(i = 1 ; i < tot ; i ++ ) printf("%d " , sta[i]);
if(tot) printf("%d" , sta[tot]);
return 0;
}

【bzoj2384】[Ceoi2011]Match 特殊匹配条件的KMP+树状数组的更多相关文章

  1. luoguP4696 [CEOI2011]Matching KMP+树状数组

    可以非常轻易的将题意转化为有多少子串满足排名相同 注意到$KMP$算法只会在当前字符串的某尾添加和删除字符 因此,如果添加和删除后面的字符对于前面的字符没有影响时,我们可以用$KMP$来模糊匹配 对于 ...

  2. 【POJ 3167】Cow Patterns (KMP+树状数组)

    Cow Patterns Description A particular subgroup of K (1 <= K <= 25,000) of Farmer John's cows l ...

  3. 【未完】训练赛20190304:KMP+树状数组+线段树+优先队列

    头炸了啊,只做出L题,前两天刚看的Shawn zhou的博客学习的,幸亏看了啊,否则就爆零了,发现题目都是经典题,线段树,KMP,我都没看过,最近又在复习考研,真后悔大一大二没好好学习啊,得抽时间好好 ...

  4. 【poj 3167】Cow Patterns(字符串--KMP匹配+数据结构--树状数组)

    题意:给2个数字序列 a 和 b ,问按从小到达排序后,a中的哪些子串与b的名次匹配. a 的长度 N≤100,000,b的长度 M≤25,000,数字的大小 K≤25. 解法:[思考]1.X 暴力. ...

  5. [bzoj1892][bzoj2384][bzoj1461][Ceoi2011]Match/字符串的匹配_KMP_树状数组

    2384: [Ceoi2011]Match 1892: Match 1461: 字符串的匹配 题目大意: 数据范围: 题解: 很巧妙的一道题呀. 需要对$KMP$算法有很深的理解才行. 首先我们需要发 ...

  6. 【bzoj4641】基因改造 特殊匹配条件的KMP

    题目描述 如果两个长度相等的字符串,如果存在一种字符的一一映射,使得第一个字符串的所有字符经过映射后与第二个字符串相同,那么就称它们“匹配”.现在给出两个串,求第一个字符串所有长度等于第二个字符串的长 ...

  7. bzoj1264 [AHOI2006]基因匹配Match 树状数组+lcs

    1264: [AHOI2006]基因匹配Match Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1255  Solved: 835[Submit][ ...

  8. 【LOJ#2507】[CEOI2011]Matching(KMP,树状数组)

    [LOJ#2507][CEOI2011]Matching(KMP,树状数组) 题面 LOJ 题解 发现要做的是排名串的匹配. 然后我们考虑把它转成这个位置之前有多少个数小于当前这个数,这样子只要每个位 ...

  9. bzoj 1264 [AHOI2006]基因匹配Match(DP+树状数组)

    1264: [AHOI2006]基因匹配Match Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 793  Solved: 503[Submit][S ...

随机推荐

  1. Django中ORM常用字段类型及参数

    常用字段: <1> CharField 字符串字段, 用于较短的字符串. CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的 ...

  2. JDK7 新特性

    JDK7新特性的目录导航: 二进制字面值 switch 语句支持 String try-with-resources catch 多个类型异常 字面值中使用下划线 类型推断 改进泛型类型可变参数 其它 ...

  3. npm 如何提升最新版本

    首先我们查看一下npm当前版本,打开cmd 运行命令: npm -v 如果不是最新版本,运行一下代码即可. npm install -g npm 这样npm就更新到最新版本了. 如果想更新到指定版本, ...

  4. html 弹框 优化 alert

    <!DOCTYPE html> <html> <head> <title>cs</title> </head> <styl ...

  5. Educational Codeforces Round 47 (Rated for Div. 2) :B. Minimum Ternary String

    题目链接:http://codeforces.com/contest/1009/problem/B 解题心得: 题意就是给你一个只包含012三个字符的字符串,位置并且逻辑相邻的字符可以相互交换位置,就 ...

  6. 总结Verilog中always语句的使用

    always语句包括的所有行为语句构成了一个always语句块.该always语句块从仿真0时刻开始执行其中的行为语句:最后一条执行完成后,再开始执行其中的第一条语句,如此往复循环,直到整个仿真结束. ...

  7. sqlserver 数据查询效率优化

    首先优化是具体情况具体分析,从硬件.改进表结构.索引.改进sql查询语句.存储方式都有关系等多方面入手 比如单表数据量(100w-200w条)不大的情况下,查询效率慢 可以从优化sql语句.对多个排序 ...

  8. linux安装oracle远程客户端

    文章参考:http://blog.csdn.net/caomiao2006/article/details/11901123 感谢博友分享O(∩_∩)O~ 安装oracle 远程客户端(一般情况下本地 ...

  9. Java的框架是什么意思

    框架就是一些类和接口的集合,通过这些类和接口协调来完成一系列的程序实现. JAVA框架可以分为三层:表示层,业务层和物理层.框架又叫做开发中的半成品,它不能提供整个WEB应用程序的所有东西,但是有了框 ...

  10. SetWindowPos,RegisterHotKey,GlobalAddAtom的用法

    还以为SetWindowPos是给Frm的子框架间编写的,原来是给mainfrm写的,可以把你写的主窗口置顶,置底(看样子应该可以变成桌面了,还没试呢,才忙到现在...) 子窗口的遮挡可以使用窗口的样 ...