题意:给一个主串,再给出多个模式串,分别求主串中有多少个连续子串,与模式串循环同构。

题解:后缀自动机
因为要求循环同构,所以将模式串复制放到后面。(要么加终止符,要么传入长度)
先对主串建sam,然后跑拓扑,自底向上更新 c n t cnt cnt( t o p s a m [ ] topsam[] topsam[]),然后求 L C S LCS LCS。
如果长度大于等于 l l l,跳 f a fa fa指针到长度为 l l l的节点 while (p->fa && p->fa->len >= l) p = p->fa;。那么此时状态所表示的子串个数 c n t cnt cnt即为所求,因为状态可能重复,用 v i s vis vis标记一下有没有被访问过即可 if (p->vis != id) p->vis = id, ans += p->cnt;
记得初始化 n o d e node node中新增变量。

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<fstream>
#include<set>
#include<map>
#define ll long long
using namespace std;
const int CHAR = 26;
const int MAXN = 1000010;
struct SAM_Node {SAM_Node* fa, * next[CHAR];int len;int id, pos;int vis, cnt;SAM_Node() {}SAM_Node(int _len) {fa = 0;len = _len;memset(next, 0, sizeof(next));}
};
SAM_Node SAM_node[MAXN * 2], * SAM_root, * SAM_last, * topsam[MAXN * 2];
int SAM_size, topcnt[MAXN * 2];
SAM_Node* newSAM_Node(int len) {SAM_node[SAM_size] = SAM_Node(len);SAM_node[SAM_size].id = SAM_size;SAM_node[SAM_size].cnt = SAM_node[SAM_size].vis = 0;return &SAM_node[SAM_size++];
}
SAM_Node* newSAM_Node(SAM_Node* p) {SAM_node[SAM_size] = *p;SAM_node[SAM_size].id = SAM_size;SAM_node[SAM_size].cnt = SAM_node[SAM_size].vis = 0;return &SAM_node[SAM_size++];
}
void SAM_init() {SAM_size = 0;SAM_root = SAM_last = newSAM_Node(0);SAM_node[0].pos = 0;
}
void SAM_add(int x, int len) {  //len从1开始SAM_Node* p = SAM_last, * np = newSAM_Node(p->len + 1);np->pos = len;SAM_last = np;for (; p && !p->next[x]; p = p->fa)p->next[x] = np;if (!p) {np->fa = SAM_root;return;}SAM_Node* q = p->next[x];if (q->len == p->len + 1) {np->fa = q;return;}SAM_Node* nq = newSAM_Node(q);nq->len = p->len + 1;q->fa = np->fa = nq;for (; p && p->next[x] == q; p = p->fa) p->next[x] = nq;
}
void SAM_build(char* s) {SAM_init();int len = strlen(s);for (int i = 0; i < len; i++) SAM_add(s[i] - 'a', i + 1);SAM_Node* p = SAM_root;for (int i = 0; i < len; i++) {p = p->next[s[i] - 'a'];p->cnt = 1;}
}
void topo() {memset(topcnt, 0, sizeof(topcnt));for (int i = 0; i <= SAM_size; i++) topcnt[SAM_node[i].len]++;for (int i = 1; i <= SAM_size; i++) topcnt[i] += topcnt[i - 1];for (int i = 0; i <= SAM_size; i++) topsam[--topcnt[SAM_node[i].len]] = &SAM_node[i];
}
void LCS(char* s, int id, int l) {int ans = 0, len = 0;SAM_Node* p = SAM_root;//cout << strlen(s) << endl;for (int i = 0; i < (l << 1) - 1; i++) {int idx = s[i] - 'a';if (p->next[idx]) p = p->next[idx], len++;else {while (p && !p->next[idx]) p = p->fa;if (!p) p = SAM_root, len = 0;else len = p->len + 1, p = p->next[idx];}//ans = max(ans, len);if (len >= l) {while (p->fa && p->fa->len >= l) p = p->fa;if (p->vis != id) p->vis = id, ans += p->cnt;}}printf("%d\n", ans);
}
char s[MAXN], t[MAXN];
int q;
int main() {scanf("%s%d", s, &q);SAM_build(s);topo();for (int i = SAM_size; i >= 2; i--) topsam[i]->fa->cnt += topsam[i]->cnt;while (q--) {scanf("%s", t);int len = strlen(t);for (int i = len; i < (len << 1) - 1; i++) t[i] = t[i - len];LCS(t, q + 1, len);}return 0;
}

CodeForces 235C Cyclical Quest (后缀自动机)相关推荐

  1. Codeforces 235C Cyclical Quest (后缀自动机)

    题目链接: https://codeforces.com/contest/235/problem/C 题解: 对大串建后缀自动机 对询问串复制拆环.这里一定要注意是复制一个循环节不是复制整个串!循环节 ...

  2. Codeforces #235 C.Cyclical Quest(后缀自动机)

    传送门 题意:给定一个模式串和nnn个匹配串,询问原串有多少个子串和匹配串循环同构 考虑要求循环同构,于是先对SSS建出后缀自动机 把每次询问的XXX倍长在自动机上跑 如果当前匹配的长度已经超过原串长 ...

  3. Codeforces.700E.Cool Slogans(后缀自动机 线段树合并 DP)

    题目链接 \(Description\) 给定一个字符串\(s[1]\).一个字符串序列\(s[\ ]\)满足\(s[i]\)至少在\(s[i-1]\)中出现过两次(\(i\geq 2\)).求最大的 ...

  4. 后缀自动机(探索)Codeforces 427D

    想学后缀自动机的 弱鸡 表示真自闭啊 开局一道题,内容全靠水 :Codeforces 427D 有题目才能更好地学 算法 题意很简单 :给两个字符串,求最短公共子串 的长度 后缀自动机 模板很多 ,给 ...

  5. CodeForces - 427D Match Catch(后缀数组/广义后缀自动机)

    题目链接:点击查看 题目大意:给出两个字符串,求出两个字符串中的最短公共子串,且在每个字符串中只出现过一次 题目分析:因为这个公共子串只能在字符串中出现一次,考虑到用后缀数组,我们先将两个字符串通过特 ...

  6. Codeforces Round #364 (Div. 1) (差一个后缀自动机)

    B. Connecting Universities 大意: 给定树, 给定2*k个点, 求将2*k个点两两匹配, 每个匹配的贡献为两点的距离, 求贡献最大值 单独考虑每条边$(u,v)$的贡献即可, ...

  7. Codeforces 235C

    Codeforces 235C 题目:给定一主串\(S\),\(n\)次询问,每次询问串\(t\)的所有循环移位串的出现的次数和 做法:建\(SAM\),对于询问串\(t\),将他复制一份放在后边,在 ...

  8. CF 316G3 Good Substrings——广义后缀自动机

    题目:http://codeforces.com/contest/316/problem/G3 对询问串和模式串一起建一个后缀自动机,做出在每个串上的 right 集合大小之后枚举自动机上的每个点看看 ...

  9. 【POJ1509】Glass Beads 【后缀自动机】

    题意 给出一个字符串,求它的最小表示法. 分析 这个题当然可以用最小表示法做啦!但是我是为了学后缀自动机鸭! 我们把这个字符串长度乘二,然后建SAM,然后在SAM上每次跑最小的那个字母,找出长度为n的 ...

最新文章

  1. Maya2022基础入门学习教程
  2. 使用MasterPage遇到的问题
  3. pytorch 笔记: 扩展torch.autograd
  4. 微软发布3款SQL Injection攻击检测工具
  5. RNN循环神经网络实现预测比特币价格过程详解
  6. C#Convert.ToInt32(byte)方法-将字节值转换为int
  7. Web前端——JavaScript(dom文档对象模型)
  8. 什么是事件?JS中都有哪些事件?
  9. docker宿主机访问容器_Docker容器与宿主机器通过IP内外通讯
  10. MVVM教程[资源+分析]
  11. C语言基础篇(零)gcc编译和预处理
  12. MySQL中的索引使用
  13. OSError: Initializing from file failed
  14. 28. (附加)字符串的组合(C++版本)
  15. 【挖坑系列】关于浏览器の缓存机制
  16. Matlab图例legend换行
  17. java实现客户端 与服务端的对话_Socket实现单客户端与服务器对话功能
  18. Huggingface Transformers库学习笔记(二):使用Transformers(上)(Using Transformers Part 1)
  19. 饥荒联机版连不上服务器_饥荒无法连接klei服务器刷不出服务器解决办法
  20. MyBatis从入门到精通(三):MyBatis XML方式的基本用法之多表查询

热门文章

  1. 【科技、商业和管理】看剧学创业:《硅谷》第五季第1-3集
  2. mycat mysql程序_MyCat + MySQL 主从部署流程(上)
  3. python处理金融数据_Python 数据分析中金融数据的来源库和简单操作
  4. 如何恢复电脑断电了丢失文件呢
  5. 代理服务器和路由器什么区别?
  6. Mel Spectrogram
  7. Unity VR 开发教程 OpenXR+XR Interaction Toolkit(八)手指触控 Poke Interaction
  8. 10句撩人的英语情话带翻译 情人节给爱人不一样爱
  9. 浏览器显示“网站连接不安全”怎么解决 怎么解除网站连接不安全
  10. QQ/微信里被禁止访问的网页怎么处理 如何检测域名是否被微信封禁 屏蔽