传送门

原本的想法是把所有的串不管是名字还是询问都连起来,记录一下询问串在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. 通过WMIC导出系统日志

    查看日志类型 wmic nteventlog get filename C:\>wmic nteventlog get filename FileName appevent secevent s ...

  2. cv2.solvepnp 相机的位姿估计

    预备知识   图像坐标系:   理想的图像坐标系原点O1和真实的O0有一定的偏差,由此我们建立了等式(1)和(2),可以用矩阵形式(3)表示. 相机坐标系(C)和世界坐标系(W): 通过相机与图像的投 ...

  3. Context 使用不当造成内存泄露

    问题: Activity中的context被传递给了一个生命周期长过activity的对象(通常为静态单实例变量),导致activity不能正常被销毁. 示例:Activity 调用 ChatMgr ...

  4. 生成gt数据出问题

    使用cout打印uchar类型数据时,打印出来是其相应的ascii码

  5. python_96_类的继承1

    #面向对象3大特性:封装,多态,继承 # 继承可节省内存,减少代码 class People(): def __init__(self,name,age): self.Name=name self.A ...

  6. 课外作业1:将一个double类型的小数,按照四舍五入保留两位小数

    package come.one01; public class One02 { public static void main(String[] args) { double numa = 3.14 ...

  7. Python基础篇 -- 集合

    set集合 set 中的元素是不重复的,无序的 里面的元素必须是可hash的,(int str tuple bool) set 就是dict 类型的数据,但是不保存value 只保存 key set集 ...

  8. Linux运维笔记--第二部

    第2部-重要目录结构详解 1.回顾Linux目录结构知识 /dev/            设备目录 /etc/             系统配置及服务配置文件,启动命令的目录 /proc       ...

  9. d3.js--03(增删改查)

    选择元素 d3.select():是选择所有指定元素的第一个 d3.selectAll():是选择指定元素的全部 插入元素 append():在选择集末尾插入元素 insert():在选择集前面插入元 ...

  10. 20180901 JavaScript闭包和匿名函数自动调用

    引用: 1. JavaScript闭包_by runoob 2. JS中(function(){xxx})这么写是什么意思? (一)闭包是可以访问上一层函数作用域里变量的函数,即便上一层函数已经关闭. ...