广义后缀自动机(广义SAM)
jiazhaopeng · · 个人记录
参考博客:【学习笔记】字符串—广义后缀自动机
基础部分:后缀自动机(SAM)
广义后缀自动机适用于多串的子串问题。它的DFA可以识别多串中的任意一个子串。同时也有类似 SAM 的一些性质。
知识精要
广义SAM 的建立
模板提交处
根据参考博客所说,有好几种 假 写法。比如:每一个串的开头设置
正规写法:
离线做法
例题:P3346 [ZJOI2015]诸神眷顾的幻想乡
建出所有串的
inline void work() {
for (register int c = 0; c < 26; ++c)
if (trie[1][c]) que[++rear] = trie[1][c];
pos[1] = 1;
while (front < rear) {
int cur = que[++front];
pos[cur] = ins(t_c[cur], pos[t_fa[cur]]);
for (register int c = 0; c < 26; ++c)
if (trie[cur][c]) que[++rear] = trie[cur][c];
}
}
在线做法
每一个串的开头设置
特判一
if (son[lst][c] && len[son[lst][c]] == len[lst] + 1) return son[lst][c];
如果有一个完美的节点
特判二
//...
//if (len[q] == len[p] + 1) return ...
if (p == lst) flag = true;
//int nq = ++tot; len[nq]...
如果存在一个不那么完美的节点
代码
inline int ins(int c, int lst) {
if (son[lst][c] && len[son[lst][c]] == len[lst] + 1) return son[lst][c];
int np = ++tot, p = lst;
len[np] = len[p] + 1;
while (p && !son[p][c]) son[p][c] = np, p = fa[p];
if (!p) return fa[np] = 1, np;
int q = son[p][c];
if (len[q] == len[p] + 1) return fa[np] = q, np;
bool flag = false;
if (p == lst) flag = true;
int nq = ++tot; len[nq] = len[p] + 1;
fa[nq] = fa[q], fa[q] = fa[np] = nq;
memcpy(son[nq], son[q], sizeof(son[q]));
while (p && son[p][c] == q) son[p][c] = nq, p = fa[p];
return flag ? nq : np;
}
在线做法由于空间开得小,码量也小,一般使用在线做法,但是离线做法的思想也要知道。
在建立广义SAM的同时,还可以维护每个串的
技能展示
识别某串是否是多串中某串的子串
直接建广义SAM,在DFA上跑即可。
多串中本质不同子串个数
建广义SAM,
维护每个串的 endpos 集合
在加入(
求多串最长公共子串
SP1812 LCS2 - Longest Common Substring II
建立多串的广义SAM,同时维护每个串的
例题
#3473. 字符串
调到心态爆炸,暂时放弃。
记录在这里:my record
附
模板(调试用)
inline int ins(int c, int lst) {
if (son[lst][c] && len[son[lst][c]] == len[lst] + 1) return son[lst][c];
int np = ++tot, p = lst;
len[np] = len[p] + 1;
while (p && !son[p][c]) son[p][c] = np, p = fa[p];
if (!p) return fa[np] = 1, np;
int q = son[p][c];
if (len[q] == len[p] + 1) return fa[np] = q, np;
bool flag = false;
if (p == lst) flag = true;
int nq = ++tot; len[nq] = len[p] + 1;
fa[nq] = fa[q], fa[q] = fa[np] = nq;
memcpy(son[nq], son[q], sizeof(son[q]));
while (p && son[p][c] == q) son[p][c] = nq, p = fa[p];
return flag ? nq : np;
}
Continued...