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

题解:后缀自动机
因为要求循环同构,所以将模式串复制放到后面。(要么加终止符,要么传入长度)
先对主串建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. Python for循环本质
  2. jquery遍历多个li_jQuery中10个非常有用的遍历函数
  3. 在bcb中添加activex控件_LinkedCell 属性介绍,OLEObjects 控件
  4. 数据库-优化-数据库结构的优化-拆分优化
  5. NLTK找出最频繁的名词标记的程序(代码详细解释)
  6. hadoop 部分问题
  7. [转]locate命令的使用
  8. AJAX设置光标离开自动提交,Ajax自动提交和刷新页面
  9. python中协程与函数的区别_python协程和异步IO
  10. c语言读取文件属性,Java File类(文件操作类)详解
  11. php 用户控件,一个使用用户控件(包括组件)的演示-.NET教程,组件控件开发
  12. 汽车电子控制系统的构成
  13. git使用命令行首次提交代码
  14. linux fat32转ntfs,fat32怎么转换ntfs格式?不损坏数据FAT32转NTFS命令是什么 电脑维修技术网...
  15. 马化腾回应《腾讯没有梦想》是网友杜撰PS
  16. BAT等互联网公司薪资分享
  17. SpringCloud_Eureka:java.lang.NoClassDefFoundError: org/springframework/boot/actuate/health/HealthAgg
  18. jQuery JSON jPlayer实现QQ空间音乐查询
  19. C++11之emplace_back
  20. 小程序中实现关注公众号

热门文章

  1. 持续请求/socket.io/?EIO=3transport=pollingt=N8HrzIR
  2. week_06_动态代理,工厂方法,单例,File,IO,网络编程,反射,数据库语句
  3. android支付功能开发,对接支付宝支付接口开发详细步骤
  4. nth-child选择器;奇数偶数作为关键字
  5. Eclipse配置Tomcat教程
  6. angular7中文件下载功能(图片、文档)
  7. PoPo数据可视化第7期
  8. 盘点im即时通讯开发中Android后台保活方案
  9. 黑马程序员 手写山寨版的金山词霸
  10. ExpandableListView始终展开不收缩