一、SAM的性质:
SAM是个状态机。一个起点,若干终点。原串的所有子串和从SAM起点开始的所有路径一一对应,不重不漏。所以终点就是包含后缀的点。
每个点包含若干子串,每个子串都一一对应一条从起点到该点的路径。且这些子串一定是里面最长子串的连续后缀。
SAM问题中经常考虑两种边:
(1) 普通边,类似于Trie。表示在某个状态所表示的所有子串的后面添加一个字符。
(2) Link、Father。表示将某个状态所表示的最短子串的首字母删除。这类边构成一棵树。
二、SAM的构造思路
endpos(s):子串s所有出现的位置(尾字母下标)集合。SAM中的每个状态都一一对应一个endpos的等价类。
endpos的性质:
(1) 令 s1,s2 为 S 的两个子串 ,不妨设 |s1|≤|s2| (我们用 |s| 表示 s 的长度 ,此处等价于 s1 不长于 s2 )。则 s1 是 s2 的后缀当且仅当 endpos(s1)⊇endpos(s2) ,s1 不是 s2 的后缀当且仅当 endpos(s1)∩endpos(s2)=∅ 。
(2) 两个不同子串的endpos,要么有包含关系,要么没有交集。
(3) 两个子串的endpos相同,那么短串为长串的后缀。
(4) 对于一个状态 st ,以及任意的 longest(st) 的后缀 s ,如果 s 的长度满足:|shortest(st)|≤|s|≤|longsest(st)| ,那么 s∈substrings(st) 。
SAM的应用
1可以将其看作一字符串的hash表,用于查询
2求该字符串的不同子串的数量//每一个点包括的字符串集合
3求某一子串在该改串的出现次数->划分endpos,递归的找
给定一个长度为 n 的只包含小写字母的字符串 S。
对于所有 S 的出现次数不为 1 的子串,设其 value 值为该子串出现的次数 × 该子串的长度。
请计算,value 的最大值是多少。
输入格式
共一行,包含一个由 n个小写字母构成的字符串。
输出格式
共一行,输出一个整数,表示答案。
数据范围
1≤n≤1e6
保证至少存在一个子串出现次数大于 11。
输入样例:
aabab
输出样例:
4
#include <iostream> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; const int N = 2000010; int tot = 1, last = 1; struct Node { int len, fa; int ch[26]; }node[N]; char str[N]; LL f[N], ans; int h[N], e[N], ne[N], idx; void extend(int c) { int p = last, np = last = ++ tot; f[tot] = 1; node[np].len = node[p].len + 1; for (; p && !node[p].ch[c]; p = node[p].fa) node[p].ch[c] = np; if (!p) node[np].fa = 1; else { int q = node[p].ch[c]; if (node[q].len == node[p].len + 1) node[np].fa = q; else { int nq = ++ tot; node[nq] = node[q], node[nq].len = node[p].len + 1; node[q].fa = node[np].fa = nq; for (; p && node[p].ch[c] == q; p = node[p].fa) node[p].ch[c] = nq; } } } void add(int a, int b) { e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ; } void dfs(int u) { for (int i = h[u]; ~i; i = ne[i]) { dfs(e[i]); f[u] += f[e[i]]; } if (f[u] > 1) ans = max(ans, f[u] * node[u].len); } int main() { scanf("%s", str); for (int i = 0; str[i]; i ++ ) extend(str[i] - 'a'); memset(h, -1, sizeof h); for (int i = 2; i <= tot; i ++ ) add(node[i].fa, i); dfs(1); printf("%lld ", ans); return 0; }
作者:yxc
链接:https://www.acwing.com/activity/content/code/content/585844/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。