http://www.spoj.com/problems/JZPGYZ/

查询一个询问串在上面n个串中多少个串的子串。

后缀数组+主席树,常熟有点大。。。

建出广义SAM,利用parent树的dfs序,每次相当于询问parent树的一个子树中出现了多少不同的颜色。

可以用主席树统计,pre表示dfs序上与这个位置属于同一个串的前一个位置在哪,主席树询问区间内的pre小于这个区间左端点的个数(也就是不同的颜色数)。

或者更方便地,把每个询问拆成parent树dfs序上的两个前缀和相减。

离线排序前缀和从左到右用bits维护pre为权值的树状数组并且查询小于某个区间左端点的pre的个数,统计答案时做一下减法就可以了(类似主席树)。

时间复杂度\(O(n\log n)\)。

还有不科学的暴力的做法,对于n个模板串,暴力在parent树上打标记,时间复杂度\(O(n^2)\)。

数据并没有卡这种做法。于是我本着复习广义后缀自动机的原则(和懒得写bits的原则),只写了这种暴力的做法。。。

将近花了一天重新脑补了一下广义SAM,感觉以前直接套用普通SAM的插入模板导致多出来了一些点不美观(当然多出来的这些点都可以合并到它们的parent),就重写了一下不会多出来点的广义SAM模板,常数更大,代码更长qwq,但保证所有节点的Right集合都是它们parent的Right集合的真子集(及不用费心想着哪些点可以合并在一起了)。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; const int N = 360003; char s[N];
int l[N], r[N]; struct State {
State *par, *go[50];
int val, tim, cnt;
State(int _num) : val(_num) {
par = 0; tim = cnt = 0;
memset(go, 0, sizeof(go));
}
} *root, *last; void extend(int w) {
if (last->go[w] && last->go[w]->val == last->val + 1) {last = last->go[w]; return;}
State *p = last;
State *np = new State(p->val + 1);
while (p && p->go[w] == 0)
p->go[w] = np, p = p->par;
if (p == 0) np->par = root;
else {
State *q = p->go[w];
if (q->val == p->val + 1) np->par = q;
else if (p != last) {
State *nq = new State(p->val + 1);
memcpy(nq->go, q->go, sizeof(q->go));
nq->par = q->par; q->par = np->par = nq;
while (p && p->go[w] == q)
p->go[w] = nq, p = p->par;
} else {
memcpy(np->go, q->go, sizeof(q->go));
np->par = q->par; q->par = np;
while (p && p->go[w] == q)
p->go[w] = np, p = p->par;
}
}
last = np;
} void mark(State *t, int timing) {
if (t == root || t->tim == timing) return;
t->tim = timing; ++t->cnt;
mark(t->par, timing);
} int n, m; int main() {
root = new State(0);
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) {
l[i] = r[i - 1] + 1;
scanf("%s", s + l[i]);
r[i] = l[i] + strlen(s + l[i]) - 1;
} for (int i = 1; i <= n; ++i) {
last = root;
for (int j = l[i], top = r[i]; j <= top; ++j)
extend(s[j] - 'a');
} State *tmp;
for (int i = 1; i <= n; ++i) {
tmp = root;
for (int j = l[i], top = r[i]; j <= top; ++j) {
tmp = tmp->go[s[j] - 'a'];
mark(tmp, i);
}
} int len; bool flag;
for (int i = 1; i <= m; ++i) {
scanf("%s", s);
len = strlen(s);
tmp = root; flag = true;
for (int j = 0; j < len; ++j)
if (tmp->go[s[j] - 'a'])
tmp = tmp->go[s[j] - 'a'];
else {
flag = false;
break;
}
if (!flag) puts("0");
else printf("%d\n", tmp->cnt);
}
return 0;
}

【SPOJ 8093】Sevenk Love Oimaster的更多相关文章

  1. SPOJ 8093 JZPGYZ - Sevenk Love Oimaster

    思路 可以用复杂度不对的做法水过去 相当于求parent树子树中的颜色种数,可以离线后树状数组(HH的项链,询问右端点排序之后维护last),dsu on tree,莫队都可以 但是也可以记录每个点上 ...

  2. 【BZOJ2780】【SPOJ】Sevenk Love Oimaster(后缀自动机)

    [BZOJ2780][SPOJ]Sevenk Love Oimaster(后缀自动机) 题面 BZOJ 洛谷 题解 裸的广义后缀自动机??? 建立广义后缀自动机建立出来之后算一下每个节点被几个串给包括 ...

  3. 【 SPOJ - GRASSPLA】 Grass Planting (树链剖分+树状数组)

    54  种草约翰有 N 个牧场,编号为 1 到 N.它们之间有 N − 1 条道路,每条道路连接两个牧场.通过这些道路,所有牧场都是连通的.刚开始的时候,所有道路都是光秃秃的,没有青草.约翰会在一些道 ...

  4. 【bzoj2780】 Sevenk Love Oimaster

    http://www.lydsy.com/JudgeOnline/problem.php?id=2780 (题目链接) 题意 给出很多主串和很多询问串,求一个询问串在多少主串中出现过 Solution ...

  5. 【BZOJ2780】Sevenk Love Oimaster【广义后缀自动机】

    题意 给出你n个字符串和q个查询,每个查询给出一个字符串s,对于每个查询你都要输出这个字符串s在上面多少个字符串中出现过. 分析 广义后缀自动机的裸题.建好SAM以后再跑一遍得到每个状态的ocu和la ...

  6. 【SPOJ 2319】 BIGSEQ - Sequence (数位DP+高精度)

    BIGSEQ - Sequence You are given the sequence of all K-digit binary numbers: 0, 1,..., 2K-1. You need ...

  7. 【SPOJ 694】Distinct Substrings (更直接的求法)

    [链接]h在这里写链接 [题意] 接上一篇文章 [题解] 一个字符串所有不同的子串的个数=∑(len-sa[i]-height[i]) [错的次数] 0 [反思] 在这了写反思 [代码] #inclu ...

  8. 【SPOJ 694】Distinct Substrings

    [链接]h在这里写链接 [题意]     给你一个长度最多为1000的字符串     让你求出一个数x,这个x=这个字符串的不同子串个数; [题解]     后缀数组题.     把原串复制一份,加在 ...

  9. 【SPOJ DQUERY】区间数字统计

    [链接] 我是链接,点我呀:) [题意] 题意 [题解] 因为区间的端点移动一个单位的话,只会涉及到一个元素的增多或减少. 因此可以用莫队算法来解决. 只需要开一个数组(大小1百万),用下标来快速检索 ...

随机推荐

  1. 【BZOJ3998】弦论 [SAM]

    弦论 Time Limit: 10 Sec  Memory Limit: 256 MB[Submit][Status][Discuss] Description 对于一个给定长度为N的字符串,求它的第 ...

  2. 炒鸡简单的canvas粒子(山东数漫江湖)

    位图的canvas一直不会被svg比下去的原因了. 俗话说,须弥芥子,是大小之说,也有以小见大之说,颗颗粒子,足以构建宏大效果. 这是一篇炒鸡简单的canvas粒子教程,主要是讲如何粒子特效的原理,一 ...

  3. MSSQL 错误:在将 varchar 值 '1,2,3,5,6' 转换成数据类型 int 时失败。

    MSSQL  错误:在将 varchar 值 '1,2,3,5,6' 转换成数据类型 int 时失败.

  4. Spring Cloud Eureka服务注册源码分析

    Eureka是怎么work的 那eureka client如何将本地服务的注册信息发送到远端的注册服务器eureka server上.通过下面的源码分析,看出Eureka Client的定时任务调用E ...

  5. Windows平台下搭建Git服务器的图文教程

    Git没有客户端服务器端的概念,但是要共享Git仓库,就需要用到SSH协议(FTP , HTTPS , SFTP等协议也能实现Git共享,此文档不讨论),但是SSH有客户端服务器端,所以在window ...

  6. Win10默认浏览器怎么设置

    1.首先在Win10桌面左下角的开始菜单图标上右键单击鼠标,在弹出的菜单选项中,点击进入“控制面板”,如下图所示. 接下来就可以找到“默认程序”设置了,找到后点击进入设置,如下图所示. 打开Win10 ...

  7. selenium遇到的一些问题,持续更新

    1.今天早上运行程序的时候,发现我在循环点击一个元素的时候出现了错误 selenium.common.exceptions.StaleElementReferenceException: Messag ...

  8. python爬虫模块之调度模块

    调度模块也就是对之前所以的模块的一个调度,作为一个流水的入口. 下面的代码的获取数据部分暂时没有写,细节部分在实际开发中,要根据要求再定义,这里说的是使用方法 from savedb import D ...

  9. MSCL超级工具类(C#),开发人员必备,开发利器

    MSCL超强工具类库 是基于C#开发的超强工具类集合,涵盖了日常B/S或C/S开发的诸多方面,包含上百个常用封装类(数据库操作类全面支持Mysql.Access.Oracle.Sqlserver.Sq ...

  10. HTML+CSS+JS(+Vue)写一个通讯录组件

    求各位大大的Star(*/ω\*). 没有录屏,所以上传的是图片.后面已补充录屏效果. 效果:(主要是参考小米Note3的通讯录的效果做的) 主要功能: 1. 滚动后,通讯录的模块标题会固定在顶部(图 ...