【bzoj2384】[Ceoi2011]Match 特殊匹配条件的KMP+树状数组
题目描述
给出两个长度分别为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+树状数组的更多相关文章
- luoguP4696 [CEOI2011]Matching KMP+树状数组
可以非常轻易的将题意转化为有多少子串满足排名相同 注意到$KMP$算法只会在当前字符串的某尾添加和删除字符 因此,如果添加和删除后面的字符对于前面的字符没有影响时,我们可以用$KMP$来模糊匹配 对于 ...
- 【POJ 3167】Cow Patterns (KMP+树状数组)
Cow Patterns Description A particular subgroup of K (1 <= K <= 25,000) of Farmer John's cows l ...
- 【未完】训练赛20190304:KMP+树状数组+线段树+优先队列
头炸了啊,只做出L题,前两天刚看的Shawn zhou的博客学习的,幸亏看了啊,否则就爆零了,发现题目都是经典题,线段树,KMP,我都没看过,最近又在复习考研,真后悔大一大二没好好学习啊,得抽时间好好 ...
- 【poj 3167】Cow Patterns(字符串--KMP匹配+数据结构--树状数组)
题意:给2个数字序列 a 和 b ,问按从小到达排序后,a中的哪些子串与b的名次匹配. a 的长度 N≤100,000,b的长度 M≤25,000,数字的大小 K≤25. 解法:[思考]1.X 暴力. ...
- [bzoj1892][bzoj2384][bzoj1461][Ceoi2011]Match/字符串的匹配_KMP_树状数组
2384: [Ceoi2011]Match 1892: Match 1461: 字符串的匹配 题目大意: 数据范围: 题解: 很巧妙的一道题呀. 需要对$KMP$算法有很深的理解才行. 首先我们需要发 ...
- 【bzoj4641】基因改造 特殊匹配条件的KMP
题目描述 如果两个长度相等的字符串,如果存在一种字符的一一映射,使得第一个字符串的所有字符经过映射后与第二个字符串相同,那么就称它们“匹配”.现在给出两个串,求第一个字符串所有长度等于第二个字符串的长 ...
- bzoj1264 [AHOI2006]基因匹配Match 树状数组+lcs
1264: [AHOI2006]基因匹配Match Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1255 Solved: 835[Submit][ ...
- 【LOJ#2507】[CEOI2011]Matching(KMP,树状数组)
[LOJ#2507][CEOI2011]Matching(KMP,树状数组) 题面 LOJ 题解 发现要做的是排名串的匹配. 然后我们考虑把它转成这个位置之前有多少个数小于当前这个数,这样子只要每个位 ...
- bzoj 1264 [AHOI2006]基因匹配Match(DP+树状数组)
1264: [AHOI2006]基因匹配Match Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 793 Solved: 503[Submit][S ...
随机推荐
- DRF知识
- 在mac上显示网速的软件——iStat Menus 5:
在mac上显示网速的软件——iStat Menus 5: https://bjango.com/mac/istatmenus/ 注册码: Email: 982092332@qq.com SN: GAW ...
- Lavavel5.5源代码 - 限流工具
app('redis')->connection('default')->throttle('key000') // 每60秒,只能有10个资源被获取,在3秒内获取不到锁抛出异常 -> ...
- 列表排序之NB三人组附加一个希尔排序
NB三人组之 快速排序 def partition(li, left, right): tmp = li[left] while left < right: while left < ri ...
- python装饰器+递归+冒泡排序
冒泡排序 li = [33, 2, 10, 1,23,23523,5123,4123,1,2,0] for k in range(1,len(li)): for i in range(len(li) ...
- Spring BindingResult验证框架Validation特殊用法
使用注解@Valid(实体属性校验) Springboot实现 Spring实现 一.准备校验时使用的JAR validation-api-1.0.0.GA.jar:JDK的接口: hibernate ...
- java冒泡算法
public static void maopao() { int temp; int[] values = {2, 34, 0, 245}; for (int i = 0; i < value ...
- LINUX网络相关命令(转)
网络连通性 Ping:发送一个 ICMP 回声请求消息给主机,一直持续到到你按下 Ctrl+C .Ping 表示一个包通过 ICMP 从你的机器发送出去,然后在IP层得到回应.Ping 可以检测你与另 ...
- 深入浅出 Webpack
深入浅出 Webpack 评价 Webpack 凭借强大的功能与良好的使用体验,已经成为目前最流行,社区最活跃的打包工具,是现代 Web 开发必须掌握的技能之一.作者结合自身的实战经验,介绍了 Web ...
- 『JavaScript』封装
封装可以被定义为对对象的内部数据表现形式和实现细节进行隐藏.通过封装可以强制实施信息隐藏. 在JavaScript中,并没有显示的声明私有成员的关键字等.所以要想实现封装/信息隐藏就需要从另外的思路出 ...