【SPOJ 8093】Sevenk Love Oimaster
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的更多相关文章
- SPOJ 8093 JZPGYZ - Sevenk Love Oimaster
思路 可以用复杂度不对的做法水过去 相当于求parent树子树中的颜色种数,可以离线后树状数组(HH的项链,询问右端点排序之后维护last),dsu on tree,莫队都可以 但是也可以记录每个点上 ...
- 【BZOJ2780】【SPOJ】Sevenk Love Oimaster(后缀自动机)
[BZOJ2780][SPOJ]Sevenk Love Oimaster(后缀自动机) 题面 BZOJ 洛谷 题解 裸的广义后缀自动机??? 建立广义后缀自动机建立出来之后算一下每个节点被几个串给包括 ...
- 【 SPOJ - GRASSPLA】 Grass Planting (树链剖分+树状数组)
54 种草约翰有 N 个牧场,编号为 1 到 N.它们之间有 N − 1 条道路,每条道路连接两个牧场.通过这些道路,所有牧场都是连通的.刚开始的时候,所有道路都是光秃秃的,没有青草.约翰会在一些道 ...
- 【bzoj2780】 Sevenk Love Oimaster
http://www.lydsy.com/JudgeOnline/problem.php?id=2780 (题目链接) 题意 给出很多主串和很多询问串,求一个询问串在多少主串中出现过 Solution ...
- 【BZOJ2780】Sevenk Love Oimaster【广义后缀自动机】
题意 给出你n个字符串和q个查询,每个查询给出一个字符串s,对于每个查询你都要输出这个字符串s在上面多少个字符串中出现过. 分析 广义后缀自动机的裸题.建好SAM以后再跑一遍得到每个状态的ocu和la ...
- 【SPOJ 2319】 BIGSEQ - Sequence (数位DP+高精度)
BIGSEQ - Sequence You are given the sequence of all K-digit binary numbers: 0, 1,..., 2K-1. You need ...
- 【SPOJ 694】Distinct Substrings (更直接的求法)
[链接]h在这里写链接 [题意] 接上一篇文章 [题解] 一个字符串所有不同的子串的个数=∑(len-sa[i]-height[i]) [错的次数] 0 [反思] 在这了写反思 [代码] #inclu ...
- 【SPOJ 694】Distinct Substrings
[链接]h在这里写链接 [题意] 给你一个长度最多为1000的字符串 让你求出一个数x,这个x=这个字符串的不同子串个数; [题解] 后缀数组题. 把原串复制一份,加在 ...
- 【SPOJ DQUERY】区间数字统计
[链接] 我是链接,点我呀:) [题意] 题意 [题解] 因为区间的端点移动一个单位的话,只会涉及到一个元素的增多或减少. 因此可以用莫队算法来解决. 只需要开一个数组(大小1百万),用下标来快速检索 ...
随机推荐
- 【BZOJ5010】【FJOI2017】矩阵填数 [状压DP]
矩阵填数 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description 给定一个 h*w 的矩阵,矩阵的行 ...
- 【BZOJ4821】【SDOI2017】相关分析 [线段树]
相关分析 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description Frank对天文学非常感兴趣,他经 ...
- bzoj 4034: [HAOI2015]树上操作——树链剖分
Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中 ...
- Spring的使用优点
spring事物配置,声明式事务管理和基于@Transactional注解的使用 spring支持编程式事务管理和声明式事务管理两种方式. 编程式事务管理使用TransactionTemplate或者 ...
- scrapy学习笔记一
以前写爬虫都是直接手写获取response然后用正则匹配,被大佬鄙视之后现在决定开始学习scrapy 一.安装 pip install scrapy 二.创建项目 scrapy startprojec ...
- HTML5 Canvas时间效果
Canvas 时间效果: function clockTest() { var canvas = document.getElementById('canvas'); if (!(canvas &am ...
- js_同步和异步
刚开始写js那会,对这一块是知之甚少,太多太多的知识不足,致使做什么都很艰难.现在工作也有段时间了,知识也有了点积累, 写点什么分享一下. 同步和异步?这个问题是在使用ajax请求后台数据的时候出现的 ...
- Linux(Unix)密码策略问题导致root密码不能修改
Linux(Unix)密码策略问题导致root密码不能修改 发布时间: 2016-01-19 浏览次数: 1034 下载次数: 5 用户修改了密码配置文件,导致root账户修改密码时报如下错误: ...
- hadoop中setOutputKeyClass和setOutputValueClass里类型
初学mapreduce programing,纠结一天的问题如下: job.setOutputKeyClass和job.setOutputValueClas在默认情况下是同时设置map阶段和reduc ...
- python--lxml
''' xpath语法: /:在子节点里面找 //:在子子孙孙里面找 //div:查找当前网页的所有div标签 //div/p:先查找所有div标签,再找div的子标签中的p标签 //div//p:现 ...