Cyclical Quest

\[Time Limit: 3000 ms\quad Memory Limit: 524288 kB
\]

题意

给出一个字符串为 \(s\) 串,接下来 \(T\) 个查询,枚举给出一个 \(t\) 串,求出 \(t\) 的所有循环子串在 \(s\) 串中出现的次数。

思路

对于每个查询串,因为要所有循环的子串,所以可以先把 \(t\) 串在复制一份到末尾,然后去求 \(LCS\)。

  • 如果在 \(p\) 节点查询到的 \(LCS==tlen\),那么 \(p\) 表示的子串就包含一种满足条件的循环 \(t\) 串。
  • 如果 \(LCS>tlen\),那就说明 \(p\) 包含了一种循环 \(t\) 串,但是匹配长度超过了循环 \(t\) 串,那么这个串的贡献一定在其 \(father\) 上,所以我们令一个临时变量 \(tmp\) 往 \(father\) 跳去寻找这个串的贡献。
  • 最后只要计算出每个节点包含的子串的出现次数,然后把这些满足条件的值加起来就可以了。

这里我们求 \(LCS\) 时直接用中间变量 \(res\)而不用往\(father\) 更新的。比如我现在在节点 \(u\),且 \(father[p]=u\),那么 \(p\) 在 \(u\) 的 \(LCS\) 就算更大,\(u\) 往其 \(father\) 的更新过程其实和 \(p\) 往 \(father\) 的更新过程是一样的,最后会停留在同一个节点,而一个节点的贡献只要算一次,所以 \(u\) 其实可以不往上更新。

还有这题的查询有 \(1e5\),而总的查询长度才 \(1e6\),所以可能出现查询多而每个串短的情况,所以对 \(vis\) 每次去 \(memset\) 是会 \(TLE\) 的...怀疑人生

#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lowbit(x) x & (-x)
#define mes(a, b) memset(a, b, sizeof a)
#define fi first
#define se second
#define pii pair<int, int>
#define INOPEN freopen("in.txt", "r", stdin)
#define OUTOPEN freopen("out.txt", "w", stdout) typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 1e6 + 10;
const int maxm = 1e5 + 10;
const ll mod = 1e9 + 7;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-8;
using namespace std; int n, m;
int cas, tol, T; struct Sam {
int node[maxn<<1][27], step[maxn<<1], fa[maxn<<1];
int dp[maxn<<1], tax[maxn<<1], gid[maxn<<1];
int vis[maxn<<1];
int last, sz;
int newnode() {
mes(node[++sz], 0);
dp[sz] = step[sz] = fa[sz] = 0;
return sz;
}
void init() {
sz = 0;
last = newnode();
}
void insert(int k) {
int p = last, np = last = newnode();
dp[np] = 1;
step[np] = step[p]+1;
for(; p&&!node[p][k]; p=fa[p])
node[p][k] = np;
if(p==0) {
fa[np] = 1;
} else {
int q = node[p][k];
if(step[q] == step[p]+1) {
fa[np] = q;
} else {
int nq = newnode();
memcpy(node[nq], node[q], sizeof(node[q]));
fa[nq] = fa[q];
step[nq] = step[p]+1;
fa[np] = fa[q] = nq;
for(; p&&node[p][k]==q; p=fa[p])
node[p][k] = nq;
}
}
}
void handle() {
for(int i=0; i<=sz; i++) tax[i] = 0;
for(int i=1; i<=sz; i++) tax[step[i]]++;
for(int i=1; i<=sz; i++) tax[i] += tax[i-1];
for(int i=1; i<=sz; i++) gid[tax[step[i]]--] = i;
for(int i=sz; i>=1; i--) {
int u = gid[i];
dp[fa[u]] += dp[u];
}
}
int solve(char *s, int len, int id) {
int p = 1, res = 0;
int ans = 0;
for(int i=1; i<=len+len; i++) {
int k = s[i]-'a'+1;
while(p && !node[p][k]) {
p = fa[p];
res = step[p];
}
if(p == 0) {
p = 1;
res = 0;
} else {
p = node[p][k];
res++;
if(res >= len) {
int tmp = p;
while(vis[tmp]!=id &&!(step[fa[tmp]]+1<=len && len<=step[tmp])) {
vis[tmp] = id;
tmp = fa[tmp];
}
if(vis[tmp] != id) {
vis[tmp] = id;
ans += dp[tmp];
}
}
}
}
return ans;
}
} sam;
char s[maxn], t[maxn<<1]; int main() {
scanf("%s", s+1);
int slen = strlen(s+1);
sam.init();
for(int i=1; i<=slen; i++) {
sam.insert(s[i]-'a'+1);
}
sam.handle();
scanf("%d", &T);
for(int tt=1; tt<=T; tt++) {
scanf("%s", t+1);
int tlen = strlen(t+1);
for(int i=1; i<=tlen; i++) {
t[i+tlen] = t[i];
}
t[tlen+tlen+1] = '\0';
int ans = sam.solve(t, tlen, tt);
printf("%d\n", ans);
}
return 0;
}

Cyclical Quest CodeForces - 235C (后缀自动机)的更多相关文章

  1. Cyclical Quest CodeForces - 235C 后缀自动机

    题意: 给出一个字符串,给出一些子串,问每个子串分别在母串中圆环匹配的次数, 圆环匹配的意思是将该子串拆成两段再首位交换相接的串和母串匹配,比 如aaab变成baaa,abaa,aaba再进行匹配. ...

  2. Match & Catch CodeForces - 427D 后缀自动机水题

    题意: 给出两个字符串a,b,求一个字符串,这个字符串是a和b的子串, 且只在a,b中出现一次,要求输出这个字符串的最小长度. 题解: 将a串放入后缀自动机中,然后记录一下每个节点对应的子串出现的次数 ...

  3. cf 235C 后缀自动机

    题目大意 给定字符串\(S\)与\(n<=10^5\)个串\(x_1,x_2...x_n\)(总长\(\le10^6\)) 对于每个\(x_i\),输出有多少个\(S\)的子串与\(x_i\)循 ...

  4. Codeforces 235C Cyclical Quest - 后缀自动机

    Some days ago, WJMZBMR learned how to answer the query "how many times does a string x occur in ...

  5. 【CodeForces - 235C】Cyclical Quest 【后缀自动机】

    题意 给出一个字符串s1和q个询问,每个询问给出一个字符串s2,问这个询问的字符串的所有不同的周期串在s1中出现的次数的和. 分析 对于s1建后缀自动机.对于询问的每个字符串s2,我们按照处理循环串的 ...

  6. 【Codeforces235C】Cyclical Quest 后缀自动机

    C. Cyclical Quest time limit per test:3 seconds memory limit per test:512 megabytes input:standard i ...

  7. 【CF235C】Cyclical Quest(后缀自动机)

    [CF235C]Cyclical Quest(后缀自动机) 题面 洛谷 题解 大致翻译: 给定一个串 然后若干组询问 每次也给定一个串 这个串可以旋转(就是把最后一位丢到最前面这样子) 问这个串以及其 ...

  8. Codeforces 235C. Cyclical Quest

    传送门 写的时候挺蛋疼的. 刚开始的时候思路没跑偏,无非就是建个SAM然后把串开两倍然后在SAM上跑完后统计贡献.但是卡在第二个样例上就是没考虑相同的情况. 然后开始乱搞,发现会出现相同串的只有可能是 ...

  9. Codeforces 452E Three Strings(后缀自动机)

    上学期很认真地学了一些字符串的常用工具,各种 suffix structre,但是其实对后缀自动机这个部分是理解地不太透彻的,以致于看了师兄A这题的代码后,我完全看不懂,于是乎重新看回一些学习后缀自动 ...

随机推荐

  1. C基本语法

    分号 ; 在C程序中,分好是语句结束符,每个语句必须以分好结束,它表明一个逻辑实体的结束 例如: printf("Hello, World! \n"); ; 注释 // 单行注释 ...

  2. AGC039

    Contest Page A 对于一个长度为\(L\)的相同字符段,显然要花费\(\frac{L}{2}\)次操作才能使得相邻不相同.于是只需要分类讨论一下首尾字符是否相同,算出每种字符.每种长度的连 ...

  3. 从nsurlsession、Alamofire到moya

    更好的理解(抽象).更少的构建(配置).更方便的表达(语言) 一.iOS系统的网络编程(DSL概念) ios缺省的网络编程只是给出了网络编程的基本概念: urlsession.request.resp ...

  4. springMVC中controller层方法中使用private和public问题

    楼主一直习惯使用public,偶尔手误也可能使用private,但是发觉也没啥区别,都能调用service层,注入bean. 后来做一个新项目时,发觉自己以前的写的部分功能报错,当时有点懵逼,,找了半 ...

  5. 在.Net Core中使用Swagger制作接口文档

    在实际开发过程中后台开发人员与前端(移动端)接口的交流会很频繁.所以需要一个简单的接口文档让双方可以快速定位到问题所在. Swagger可以当接口调试工具也可以作为简单的接口文档使用. 在传统的asp ...

  6. Zookeeper学习笔记:简单注册中心

    zookeeper可以作为微服务注册中心,spring cloud也提供了zookeeper注册中心的支持. 本文介绍如何实现一个简单的zookeeper注册中心,主要的实现方式: n个服务提供者对外 ...

  7. 题解 POJ 2559【Largest Rectangle in a Histogram】(单调栈)

    题目链接:http://poj.org/problem?id=2559 思路:单调栈 什么是单调栈? 单调栈,顾名思义,就是单调的栈,也就是占中存的东西永远是单调(也就是递增或递减)的 如何实现一个单 ...

  8. 【转载】Asp.Net生成图片验证码工具类

    在Asp.Net应用程序中,很多时候登陆页面以及其他安全重要操作的页面需要输入验证码,本文提供一个生成验证码图片的工具类,该工具类通过随机数生成验证码文本后,再通过C#中的图片处理类位图类,字体类,一 ...

  9. vue + yarn 项目开发 (一)

    1.打开src文件夹中的main.js文件,添加引用element ui框架 import ElementUI from 'element-ui' import 'element-ui/lib/the ...

  10. C#的静态类

    静态类 静态类与非静态类的重要区别在于静态类不能实例化,也就是说,不能使用 new 关键字创建静态类类型的变量.在声明一个类时使用static关键字,具有两个方面的意义:首先,它防止程序员写代码来实例 ...