传送门

原本的想法是把所有的串不管是名字还是询问都连起来,记录一下询问串在sa数组中的位置

对于每个询问可以在sa数组中二分出左右边界,第一问用莫队,第二问差分乱搞。

结果发现我差分的思路想错了,先写了一个暴力,二分出左右边界之后直接从l枚举到r,想试试正确性,就交了一遍,结果过了。。。。

因为是暴力,可以不用二分左右边界,直接向左向右枚举扩展就可以了,st表也不用了,但我懒得改了

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#define N 2000001 using namespace std; int n, m, cnt, mx, len;
int M[N], x[N], y[N], s[N], sa[N], b[N], d[N][21], Rank[N], Log[N], height[N], id[N], pos[N], ans[N], num[N]; inline int read()
{
int x = 0, f = 1;
char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
return x * f;
} inline void build_sa()
{
int i, k, p;
for(i = 0; i < mx; i++) b[i] = 0;
for(i = 0; i < len; i++) b[x[i] = s[i]]++;
for(i = 1; i < mx; i++) b[i] += b[i - 1];
for(i = len - 1; i >= 0; i--) sa[--b[x[i]]] = i;
for(k = 1; k <= len; k <<= 1)
{
p = 0;
for(i = len - k; i < len; i++) y[p++] = i;
for(i = 0; i < len; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
for(i = 0; i < mx; i++) b[i] = 0;
for(i = 0; i < len; i++) b[x[y[i]]]++;
for(i = 1; i < mx; i++) b[i] += b[i - 1];
for(i = len - 1; i >= 0; i--) sa[--b[x[y[i]]]] = y[i];
swap(x, y);
p = 1, x[sa[0]] = 0;
for(i = 1; i < len; i++)
x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p++;
if(p >= len) break;
mx = p;
}
} inline void build_height()
{
int i, j, k = 0;
for(i = 0; i < len; i++) Rank[sa[i]] = i;
for(i = 0; i < len; i++)
{
if(k) k--;
j = sa[Rank[i] - 1];
while(s[i + k] == s[j + k]) k++;
height[Rank[i]] = k;
}
} inline void build_st()
{
int i, j;
for(i = 1; i < len; i++)
{
Log[i] = log2(i);
d[i][0] = height[i];
}
Log[i] = log2(i);
for(j = 1; (1 << j) < len; j++)
for(i = 1; i + (1 << j) - 1 < len; i++)
d[i][j] = min(d[i][j - 1], d[i + (1 << j - 1)][j - 1]);
} inline int query(int l, int r)
{
int t = Log[r - l + 1];
return min(d[l][t], d[r - (1 << t) + 1][t]);
} inline int search2(int p, int llen)
{
int r = p, l = 1, mid;
while(l <= r)
{
mid = (l + r) >> 1;
if(query(mid, p) >= llen) r = mid - 1;
else l = mid + 1;
}
return r;
} inline int search1(int p, int llen)
{
p++;
int l = p, r = len - 1, mid;
while(l <= r)
{
mid = (l + r) >> 1;
if(query(p, mid) >= llen) l = mid + 1;
else r = mid - 1;
}
return l - 1;
} inline void solve()
{
int i, j, l, r;
for(i = 1; i <= m; i++)
{
r = j = search1(Rank[id[i]], M[i]);
l = j = search2(Rank[id[i]], M[i]);
for(j = l; j <= r; j++)
if(!num[pos[sa[j]]]++ && pos[sa[j]]) cnt++, ans[pos[sa[j]]]++;
printf("%d\n", cnt);
cnt = 0;
for(j = l; j <= r; j++) num[pos[sa[j]]] = 0;
}
for(i = 1; i <= n; i++) printf("%d ", ans[i]);
} int main()
{
int i, j, t;
n = read();
m = read();
for(i = 1; i <= n; i++)
for(j = 1; j <= 2; j++)
{
t = read();
while(t--)
{
pos[len] = i;
s[len++] = read() + 100000;
}
s[len++] = mx++;
}
for(i = 1; i <= m; i++)
{
M[i] = read();
id[i] = len;
for(j = 1; j <= M[i]; j++) s[len++] = read() + 100000;
s[len++] = mx++;
}
mx = 120000;
build_sa();
build_height();
build_st();
solve();
return 0;
}

  

[luoguP2336] [SCOI2012]喵星球上的点名(后缀数组 + 暴力)的更多相关文章

  1. BZOJ 2754: [SCOI2012]喵星球上的点名 [后缀数组+暴力]

    2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1906  Solved: 839[Submit][St ...

  2. BZOJ 2754 SCOI 2012 喵星球上的点名 后缀数组 树状数组

    2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2068  Solved: 907[Submit][St ...

  3. P2336 [SCOI2012]喵星球上的点名(后缀自动机+莫队+dfs序)

    P2336 [SCOI2012]喵星球上的点名 名字怎么存?显然是后缀自动机辣 询问点到多少个喵喵喵其实就是 查询后缀自动机上parent树的一个子树 于是我们考虑莫队 怎么树上莫队呢 我们用dfs序 ...

  4. BZOJ2754: [SCOI2012]喵星球上的点名

    2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 680  Solved: 314[Submit][Sta ...

  5. 【BZOJ2754】[SCOI2012]喵星球上的点名

    [BZOJ2754][SCOI2012]喵星球上的点名 题面 bzoj 洛谷 题解 这题有各种神仙做法啊,什么暴力\(AC\)自动机.\(SAM\)等等五花八门 我这个蒟蒻在这里提供一种复杂度正确且常 ...

  6. BZOJ 2754: [SCOI2012]喵星球上的点名

    2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 649  Solved: 305[Submit][Sta ...

  7. BZOJ 2754: [SCOI2012]喵星球上的点名 [AC自动机+map+暴力]

    2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1902  Solved: 837[Submit][St ...

  8. 洛咕 P2336 [SCOI2012]喵星球上的点名

    洛咕 P2336 [SCOI2012]喵星球上的点名 先求出SA和height,一个点名串对应的就是一段区间,还有很多个点,就转化成了 有很多个区间,很多个点集,对每个区间计算和多少个点集有交,对每个 ...

  9. 洛谷 P2336 [SCOI2012]喵星球上的点名 解题报告

    P2336 [SCOI2012]喵星球上的点名 题目描述 a180285 幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有 \(N\) 个喵星人,每个喵星人的 ...

随机推荐

  1. [论文理解]Deep Residual Learning for Image Recognition

    Deep Residual Learning for Image Recognition 简介 这是何大佬的一篇非常经典的神经网络的论文,也就是大名鼎鼎的ResNet残差网络,论文主要通过构建了一种新 ...

  2. 苹果市值破万亿,iPhone 会涨价吗?

    今日导读 苹果教父乔布斯曾经说过:“活着就是为了改变世界.”虽然他在 56 岁时就遗憾离世,但他极具创新和变革的精神早已深埋进苹果公司的企业文化里,影响着一代又一代的人.就在最近,这家一直努力“改变世 ...

  3. C# 数据结构 - 单链表 双链表 环形链表

    链表特点(单链表 双链表) 优点:插入和删除非常快.因为单链表只需要修改Next指向的节点,双链表只需要指向Next和Prev的节点就可以完成插入和删除操作. 缺点:当需要查找某一个节点的时候就需要一 ...

  4. NOIP2016 toy

    题目描述 小南有一套可爱的玩具小人, 它们各有不同的职业. 有一天, 这些玩具小人把小南的眼镜藏了起来. 小南发现玩具小人们围成了一个圈,它们有的面朝圈内,有的面朝圈外.如下图: 这时singer告诉 ...

  5. 变量赋值理解--Pyton中让两个值互换的方法

    #Pyton中让两个值互换的方法 #方法一:可以理解为相当于是同时赋值 a = 5 b = 4 a,b = b,a print(a,b) #方法二:可以理解为拿箱子过程 c = 10 d = 20 e ...

  6. Helm入门

    前言:Helm是GO语言编写的,是管理kubernetes集群中应用程序包的客户端工具.Helm是类似于centos上的yum工具或Ubuntu上的apt-get工具.对于应用发布者而言,可以通过He ...

  7. CentOS7 安装操作命令

    #timedatectl set-timezone Asia/Shanghai 关闭SELinux vi /etc/sysconfig/selinux #SELINUX=enforcing SELIN ...

  8. 分享几个简单的技巧让你的 vue.js 代码更优雅

    1. watch 与 computed 的巧妙结合 一个简单的列表页面. 你可能会这么做: created(){ this.fetchData() }, watch: { keyword(){ thi ...

  9. vue $emit子组件传出多个参数,如何在父组件中在接收所有参数的同时添加自定义参数

    Vue.js 父子组件通信的十种方式 前言 很多时候用$emit携带参数传出事件,并且又需要在父组件中使用自定义参数时,这时我们就无法接受到子组件传出的参数了.找到了两种方法可以同时添加自定义参数的方 ...

  10. 使用TensorFlow的卷积神经网络识别手写数字(2)-训练篇

    import numpy as np import tensorflow as tf import matplotlib import matplotlib.pyplot as plt import ...