here:https://oi-wiki.org/string/sam/ 下面转自 KesdiaelKen的雷蒻论坛 来个广义后缀自动机模板题 [USACO17DEC]Standing Out from the Herd #include <bits/stdc++.h> using namespace std; const int MAXN = 100005; int n, l[MAXN], m, s[MAXN]; long long ans[MAXN]; namespace SAM { co…
知识点: 广义 SAM 原题面 Luogu 「扯」 随便「口胡」一下居然「过」了. 比较考验「代码能力」,第一次感觉「大模拟」没有白写((( 还有这个「符号」实在是太「上头」了. 前置知识 在线构造广义 SAM,推荐:[学习笔记]字符串-广义后缀自动机 - 辰星凌 题意简述 给定 \(n\) 个仅包含小写字母的字符串 \(S_1\sim S_n\). 定义字符串 \(S_i\) 的 「独特值」为只属于该串的本质不同的非空子串的个数. 求字符串 \(S_1\sim S_n\) 的「独特值」. \(…
题意 定义一个字符串的「独特值」为只属于该字符串的本质不同的非空子串的个数.如 "amy" 与 “tommy” 两个串,只属于 "amy" 的本质不同的子串为 "a" "am" "amy" 共 3 个.只属于 "tommy" 的本质不同的子串为 "t" "to" "tom" "tomm" "tomm…
建出广义SAM,通过parent树对每个节点求出其是否仅被一个子串包含及被哪个包含. 写了无数个sam板子题一点意思都没啊 #include<bits/stdc++.h> using namespace std; #define ll long long #define inf 1000000010 #define N 200010 char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>…
题目链接 题意 给定多个字符串,每个串中仅在该串中出现的本质不同的子串个数. Sol 多串匹配想到用广义SAM. 之后从串的匹配角度不是很好做.发现一个本质不同的串最多只会贡献到一个串的答案里. 那么建完广义SAM后,如果我们能够知道那些点是只有一个串能够到达并且知道是哪个的话我们就可以直接把这个点代表的本质不同的串给贡献到对应串的答案中. 这个很好办,我们在建广义SAM的时候不考虑串之间的匹配,建完后再拿着所有的串重新在广义SAM上跑一遍,当我们遍历到一个点(也就是该串的一个前缀)的时候,它的…
思路 对所有串建立广义SAM,之后记录SZ,统计本质不同子串时只统计SZ=1的即可 代码 #include <cstdio> #include <algorithm> #include <cstring> using namespace std; int maxlen[201000],minlen[201000],trans[201000][26],suflink[201000],ans[201000],sz[201000],last[201000],Nodecnt,n…
题目大意:给你$n$个字符串,对每个字符串求出只在这个字符串中出现的字串的个数 题解:先建广义$SAM$,然后对每个点统计一下它的子树中是不是都是在同一个字符串中的,是的话,就把这个点标成这一个字符串,计算贡献 卡点:无 C++ Code: #include <algorithm> #include <cstdio> #include <cstring> #define maxn 100010 long long ans[maxn]; namespace SAM { #…
题目 不会广义\(SAM\)啊 但信仰插入特殊字符就可以搞定一切了 我们先把所有的串搞在一起建出一个\(SAM\),记得在中间插入特殊字符 对于\(parent\)树上的一个节点,只有当其\(endpos\)集合中的所有元素都来自于同一个串的时候我们才对它进行统计 所以我们需要维护一个\(parent\)树上子树最大值和最小值,这样我们就能很快的判断这个\(endpos\)是否合法了 但是非常棘手的一类情况是我们插进去的特殊字符,显然\(SAM\)里有一些奇奇怪怪的子串中含有特殊字符 那也好办,…
题目大意: 给定一个字符串,可理解成环,然后选定一位置,逆时针或顺时针走一遍,希望得到字典序最大,如果同样大,希望找到起始位置最小的,如果还相同,就默认顺时针 比赛一直因为处理最小位置出错,一结束就想明白了...真是作孽 这里正向后缀自动机跑一遍最大的,这样得到的位置肯定是最小的 而逆时针最大就反向重建后缀自动机再跑一遍最大的,但这样因为后缀自动机跑出的位置是最小的,但返回来就变成最大的位置了 如果存在更小的位置,那么就相当于可以从开头拎出一段移到末尾,那么必然是产生一个循环节,这个长度可以利用…
题目: 题目在这里 思路&做法: 参考的题解 既然只有\(20\)个叶子节点, 那么可以从每个叶子节点往上建一颗\(trie\)树, 然后合并成一棵大的\(trie\)树, 然后构建广义后缀自动机. \((\) 实现起来就是dfs时把节点上的颜色加进广义后缀自动机\()\) 再然后就统计一下就可以了\((ans += len[x] - len[fail[x])\) 代码: #include <iostream> #include <cstring> #include <…