2384: [Ceoi2011]Match 1892: Match 1461: 字符串的匹配

题目大意

数据范围


题解

很巧妙的一道题呀。

需要对$KMP$算法有很深的理解才行。

首先我们需要发现,要求的这个东西跟字符串匹配有点像。

我们在单个模式串匹配的时候用到的$KMP$算法,合法匹配条件是两个字符完全相同。

但是这个题本质上就是要求子串离散化之后相同。

如果两个串离散化之后完全相同,等价于一个条件,就是每个数前面比它小的个数通通相等。

这是显然的。

所以我们尝试改变$KMP$的匹配模式,并且用树状数组维护长串的这个值。

先假设,所有数字两两不同。

对于要求离散化后的串,每个位置弄一个$f_i$表示这个串中,第$i$个位置前面有多少个比$b_i$小的。

我们把如图红色位置加入树状数组

然后我们查询$i$位置,有多少比$a_i$小的,跟$f_{nxt[i-1]}$相比。

如果相等表示这个位置可以匹配,如果不能,我们就把

$i-nxt_{i-1}$到$i-nxt_{nxt_{i - 1}}$。

这样就可以了。

如果离散化之后不完全相等的话,我们就考虑维护出来$i$前面和$b_i$相等的有多少个,再查就行了。

代码

#include <bits/stdc++.h>

#define N 1000010 

using namespace std;

int tree[N], a[N], b[N], c[N], rk[N], bfr[N], nxt[N], ans[N];

int n, m;

char *p1, *p2, buf[100000];

#define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )

int rd() {
int x = 0, f = 1;
char c = nc();
while (c < 48) {
if (c == '-')
f = -1;
c = nc();
}
while (c > 47) {
x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
}
return x * f;
} inline int lowbit(int x) {
return x & (-x);
} void update(int x, int val) {
for (int i = x; i <= m; i += lowbit(i))
tree[i] += val;
} int query(int x) {
int ans = 0;
for (int i = x; i; i -= lowbit(i))
ans += tree[i];
return ans;
} int main() {
n = rd(), m = rd();
for (int i = 1; i <= n; i ++ )
a[i] = rd(), rk[a[i]] = i;
for (int i = 1; i <= n; i ++ )
bfr[i] = query(rk[i]), update(rk[i], 1);
for (int i = 1; i <= m; i ++ )
b[i] = rd(), c[i] = b[i];
memset(tree, 0, sizeof tree); // for (int i = 1; i <= n; i ++ )
// printf("%d ", bfr[i]);
// puts(""); for (int i = 2, j = 0; i <= n; i ++ ) {
while (query(rk[i]) != bfr[j + 1]) {
for (int k = i - j; k < i - nxt[j]; k ++ )
update(rk[k], -1);
j = nxt[j];
}
if (query(rk[i]) == bfr[j + 1]) {
update(rk[i], 1);
j ++ ;
}
nxt[i] = j;
} // for (int i = 1; i <= n; i ++ ) {
// printf("%d ", nxt[i]);
// }
// puts(""); sort(c + 1, c + m + 1);
memset(tree, 0, sizeof tree); for (int i = 1, j = 0; i <= m; i ++ ) {
// printf("i-> %d\n", i);
b[i] = lower_bound(c + 1, c + m + 1, b[i]) - c;
// printf("%d\n", b[i]);
// printf("%d %d %d\n", j, query(b[i]), bfr[j + 1]);
while (j == n || query(b[i]) != bfr[j + 1]) {
for (int k = i - j; k < i - nxt[j]; k ++ ) {
update(b[k], -1);
}
j = nxt[j];
}
if (query(b[i]) == bfr[j + 1]) {
update(b[i], 1);
j ++ ;
}
if(j == n)
ans[ ++ ans[0]] = i - j + 1;
} printf("%d\n", ans[0]);
for (int i = 1; i < ans[0]; i ++ )
printf("%d ",ans[i]);
if(ans[0])
printf("%d\n", ans[ans[0]]);
return 0;
}

小结:好题啊,这个题真的不好想,我看题解都看了半天.......

[bzoj1892][bzoj2384][bzoj1461][Ceoi2011]Match/字符串的匹配_KMP_树状数组的更多相关文章

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

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

  2. BZOJ_1264_[AHOI2006]基因匹配Match_树状数组

    BZOJ_1264_[AHOI2006]基因匹配Match_树状数组 Description 基因匹配(match) 卡卡昨天晚上做梦梦见他和可可来到了另外一个星球,这个星球上生物的DNA序列由无数种 ...

  3. 洛谷P4303 [AHOI2006]基因匹配(树状数组)

    传送门 我已经连这种傻逼题都不会了orz 正常的dp是$O(n^2)$的,枚举第一个数组的$j$,然后第二个数组的$k$,如果相等,则$dp[i]=dp[j]+1$,否则$dp[i]=dp[j]$ 然 ...

  4. 【bzoj2384】[Ceoi2011]Match 特殊匹配条件的KMP+树状数组

    题目描述 给出两个长度分别为n.m的序列A.B,求出B的所有长度为n的连续子序列(子串),满足:序列中第i小的数在序列的Ai位置. 输入 第一行包含两个整数n, m (2≤n≤m≤1000000).  ...

  5. 【BZOJ2384】[Ceoi2011]Match KMP

    [BZOJ2384][Ceoi2011]Match Description 作为新一轮广告大战的一部分,格丁尼亚的一家大公司准备在城市的某处设置公司的标志(logo).公司经理决定用一些整栋的建筑来构 ...

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

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

  7. 【BZOJ1264】[AHOI2006]基因匹配Match DP+树状数组

    [BZOJ1264][AHOI2006]基因匹配Match Description 基因匹配(match) 卡卡昨天晚上做梦梦见他和可可来到了另外一个星球,这个星球上生物的DNA序列由无数种碱基排列而 ...

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

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

  9. BZOJ 1264: [AHOI2006]基因匹配Match 树状数组+DP

    1264: [AHOI2006]基因匹配Match Description 基因匹配(match) 卡卡昨天晚上做梦梦见他和可可来到了另外一个星球,这个星球上生物的DNA序列由无数种碱基排列而成(地球 ...

随机推荐

  1. 路由器配置——广播多路访问链路上的OSPF

    一.实验目的:作广播形式的OSPF,了解DR与BDR之间的链路关系 二.拓扑图: 三.具体步骤配置 (1)R1路由器配置 enableconfigure terminalhostname R1inte ...

  2. [python之ipython] jupyter notebook在云端服务器上开启,本地访问

    本地ssh到云端: ssh username@xxx.xxx.xxx.xxx -L127.0.0.1:7777:127.0.0.1:8888 把云端的8888端口映射到本地的7777端口 云端运行指令 ...

  3. OnUpdateError

    DataSetProvider1.OnUpdateError void __fastcall TFrmItem::Query1UpdateError(TDataSet *ASender, EFDExc ...

  4. 0079 Ehcache 3.x应用入门及通过JCache与Spring整合

    基本要素:版本.概念与抽象 Ehcache 3.x是一个用Java语言实现的缓存库,并且实现了 JSR107规范 Ehcache从2.x升级到3.x后,Maven依赖从 net.sf.ehcache: ...

  5. php &#编码/php unicode转码/php &#数字编码

    今天使PHP开发用到了Unicode的编码与解码,将unicode转为中文,再将中文转Unicode这样的操作是非常常见的,所以小编将这两个unicode中文互转函数给作为一个笔记保存起来,非常的简单 ...

  6. 使用 kubeadm 安装 kubernetes v1.16.0

    近日通过kubeadm 安装 kubernetes v1.16.0,踩过不少坑,现记录下安装过程. 安装环境: 系           统:CentOS Linux release 7.6 Docke ...

  7. Spring Cloud Eureka(四):Eureka 配置参数说明

    Eureka Client 配置项(eureka.client.*) org.springframework.cloud.netflix.eureka.EurekaClientConfigBean 参 ...

  8. P2089 烤鸡

    题目背景 猪猪hanke得到了一只鸡 题目描述 猪猪Hanke特别喜欢吃烤鸡(本是同畜牲,相煎何太急!)Hanke吃鸡很特别,为什么特别呢?因为他有10种配料(芥末.孜然等),每种配料可以放1—3克, ...

  9. 通读Python官方文档之cgi

    cgi 通用网关接口 前驱知识 网关协议学习:CGI.FastCGI.WSGI 简单点说: web服务器接受请求,启动CGI:CGI接受请求,处理,返回给服务器:服务器返回给用户 cgi效率不高,每次 ...

  10. session cookie傻傻分不清

    做了这么多年测试,还是分不清什么是cookie,什么是session?很正常,很多初级开发工程师可能到现在都搞不清什么是session,cookie相对来说会简单很多. 下面这篇文章希望能够帮助大家分 ...