From: 24OI-bot <15963390+24OI-bot@users.noreply.github.com> Date: Wed, 11 Sep 2019 03:17:53 +0000 (-0400) Subject: style: format markdown files with remark-lint X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=da9b88e8bb0bad2616f54ab8faf5062ae06543c1;p=oi-wiki%2Fmain.git style: format markdown files with remark-lint --- diff --git a/docs/string/seq-automaton.md b/docs/string/seq-automaton.md index 44f5300f..92ab127a 100644 --- a/docs/string/seq-automaton.md +++ b/docs/string/seq-automaton.md @@ -1,6 +1,6 @@ ## 定义 -序列自动机是接受且仅接受一个字符串的子序列的 [自动机](./automaton.md)。 +序列自动机是接受且仅接受一个字符串的子序列的 [自动机](./automaton.md) 。 本文中用 $s$ 代指这个字符串。 @@ -8,7 +8,7 @@ 若 $s$ 包含 $n$ 个字符,那么序列自动机包含 $n+1$ 个状态。 -令 $t$ 是 $s$ 的一个子序列,那么 $\delta(start, t)=\min\{i|t\text{ 是 }s[1..i]\text{ 的子序列}\}$。 +令 $t$ 是 $s$ 的一个子序列,那么 $\delta(start, t)=\min\{i|t\text{ 是 }s[1..i]\text{ 的子序列}\}$ 。 也就是说,一个状态 $i$ 表示前缀 $s[1..i]$ 的子序列与前缀 $s[1..i-1]$ 的子序列的差集。 @@ -16,9 +16,9 @@ ### 转移 -由状态定义可以得到,$\delta(u, c)=\min\{i|i>u,s[i]=u\}$,也就是字符 $c$ 下一次出现的位置。 +由状态定义可以得到, $\delta(u, c)=\min\{i|i>u,s[i]=u\}$ ,也就是字符 $c$ 下一次出现的位置。 -为什么是“下一次”出现的位置呢?因为若 $i>j$,后缀 $s[i..|s|]$ 的子序列是后缀 $s[j..|s|]$ 的子序列的子集,一定是选尽量靠前的最优。 +为什么是“下一次”出现的位置呢?因为若 $i>j$ ,后缀 $s[i..|s|]$ 的子序列是后缀 $s[j..|s|]$ 的子序列的子集,一定是选尽量靠前的最优。 ## 构建 @@ -43,159 +43,141 @@ $$ ???+note "[「HEOI2015」最短不公共子串](https://www.luogu.org/problem/P4112)" 这题的 (1) 和 (3) 两问需要后缀自动机,而且做法类似,在这里只讲解 (2) 和 (4) 两问。 - + (2) 比较简单,枚举 A 的子串输入进 B 的序列自动机,若不接受则计入答案。 - - (4) 需要 DP。令 $f(i, j)$ 表示在 A 的序列自动机中处于状态 $i$,在 B 的序列自动机中处于状态 $j$,需要再添加多少个字符能够不是公共子序列。 - - $f(i, null)=f(null, j)=0$ - - $f(i, j)=\min\limits_{\delta_A(i,c)\ne null}f(\delta_A(i, c), \delta_B(j, c))$ - + + (4) 需要 DP。令 $f(i, j)$ 表示在 A 的序列自动机中处于状态 $i$ ,在 B 的序列自动机中处于状态 $j$ ,需要再添加多少个字符能够不是公共子序列。 + + $f(i, null)=f(null, j)=0$ + + $f(i, j)=\min\limits_{\delta_A(i,c)\ne null}f(\delta_A(i, c), \delta_B(j, c))$ + 整道题的参考代码: - + ```cpp - #include + #include #include #include - #include + #include using namespace std; const int N = 2005; char s[N], t[N]; - int n, m, a[N], b[N], na[N][26], nb[N][26], nxt[26], tot = 1, p = 1, f[N][N << 1]; + int n, m, a[N], b[N], na[N][26], nb[N][26], nxt[26], tot = 1, p = 1, + f[N][N << 1]; - struct SAM - { - int par, ch[26], len; + struct SAM { + int par, ch[26], len; } sam[N << 1]; - void insert(int x) - { - int np = ++tot; - while (p && !sam[p].ch[x]) - { - sam[p].ch[x] = np; + void insert(int x) { + int np = ++tot; + while (p && !sam[p].ch[x]) { + sam[p].ch[x] = np; + p = sam[p].par; + } + if (p == 0) + sam[np].par = 1; + else { + int q = sam[p].ch[x]; + if (sam[q].len == sam[p].len + 1) + sam[np].par = q; + else { + int nq = ++tot; + sam[nq].len = sam[p].len + 1; + memcpy(sam[nq].ch, sam[q].ch, sizeof(sam[q].ch)); + sam[nq].par = sam[q].par; + sam[q].par = sam[np].par = nq; + while (p && sam[p].ch[x] == q) { + sam[p].ch[x] = nq; p = sam[p].par; + } } - if (p == 0) sam[np].par = 1; - else - { - int q = sam[p].ch[x]; - if (sam[q].len == sam[p].len + 1) sam[np].par = q; - else - { - int nq = ++tot; - sam[nq].len = sam[p].len + 1; - memcpy(sam[nq].ch, sam[q].ch, sizeof(sam[q].ch)); - sam[nq].par = sam[q].par; - sam[q].par = sam[np].par = nq; - while (p && sam[p].ch[x] == q) - { - sam[p].ch[x] = nq; - p = sam[p].par; - } - } - } - p = np; + } + p = np; } - int main() - { - scanf("%s%s", s + 1, t + 1); + int main() { + scanf("%s%s", s + 1, t + 1); - n = strlen(s + 1); - m = strlen(t + 1); + n = strlen(s + 1); + m = strlen(t + 1); - for (int i = 1; i <= n; ++i) a[i] = s[i] - 'a'; - for (int i = 1; i <= m; ++i) b[i] = t[i] - 'a'; + for (int i = 1; i <= n; ++i) a[i] = s[i] - 'a'; + for (int i = 1; i <= m; ++i) b[i] = t[i] - 'a'; - for (int i = 1; i <= m; ++i) insert(b[i]); + for (int i = 1; i <= m; ++i) insert(b[i]); - for (int i = 0; i < 26; ++i) nxt[i] = n + 1; - for (int i = n; i >= 0; --i) - { - memcpy(na[i], nxt, sizeof(nxt)); - nxt[a[i]] = i; - } + for (int i = 0; i < 26; ++i) nxt[i] = n + 1; + for (int i = n; i >= 0; --i) { + memcpy(na[i], nxt, sizeof(nxt)); + nxt[a[i]] = i; + } - for (int i = 0; i < 26; ++i) nxt[i] = m + 1; - for (int i = m; i >= 0; --i) - { - memcpy(nb[i], nxt, sizeof(nxt)); - nxt[b[i]] = i; - } + for (int i = 0; i < 26; ++i) nxt[i] = m + 1; + for (int i = m; i >= 0; --i) { + memcpy(nb[i], nxt, sizeof(nxt)); + nxt[b[i]] = i; + } - int ans = N; - - for (int l = 1; l <= n; ++l) - { - for (int r = l, u = 1; r <= n; ++r) - { - u = sam[u].ch[a[r]]; - if (!u) - { - ans = min(ans, r - l + 1); - break; - } - } - } + int ans = N; - printf("%d\n", ans == N ? -1 : ans); - - ans = N; - - for (int l = 1; l <= n; ++l) - { - for (int r = l, u = 0; r <= n; ++r) - { - u = nb[u][a[r]]; - if (u == m + 1) - { - ans = min(ans, r - l + 1); - break; - } - } + for (int l = 1; l <= n; ++l) { + for (int r = l, u = 1; r <= n; ++r) { + u = sam[u].ch[a[r]]; + if (!u) { + ans = min(ans, r - l + 1); + break; + } } + } + + printf("%d\n", ans == N ? -1 : ans); + + ans = N; - printf("%d\n", ans == N ? -1 : ans); - - for (int i = n; i >= 0; --i) - { - for (int j = 1; j <= tot; ++j) - { - f[i][j] = N; - for (int c = 0; c < 26; ++c) - { - int u = na[i][c]; - int v = sam[j].ch[c]; - if (u <= n) f[i][j] = min(f[i][j], f[u][v] + 1); - } - } + for (int l = 1; l <= n; ++l) { + for (int r = l, u = 0; r <= n; ++r) { + u = nb[u][a[r]]; + if (u == m + 1) { + ans = min(ans, r - l + 1); + break; + } } + } + + printf("%d\n", ans == N ? -1 : ans); + + for (int i = n; i >= 0; --i) { + for (int j = 1; j <= tot; ++j) { + f[i][j] = N; + for (int c = 0; c < 26; ++c) { + int u = na[i][c]; + int v = sam[j].ch[c]; + if (u <= n) f[i][j] = min(f[i][j], f[u][v] + 1); + } + } + } + + printf("%d\n", f[0][1] == N ? -1 : f[0][1]); + + memset(f, 0, sizeof(f)); - printf("%d\n", f[0][1] == N ? -1 : f[0][1]); - - memset(f, 0, sizeof(f)); - - for (int i = n; i >= 0; --i) - { - for (int j = 0; j <= m; ++j) - { - f[i][j] = N; - for (int c = 0; c < 26; ++c) - { - int u = na[i][c]; - int v = nb[j][c]; - if (u <= n) f[i][j] = min(f[i][j], f[u][v] + 1); - } - } + for (int i = n; i >= 0; --i) { + for (int j = 0; j <= m; ++j) { + f[i][j] = N; + for (int c = 0; c < 26; ++c) { + int u = na[i][c]; + int v = nb[j][c]; + if (u <= n) f[i][j] = min(f[i][j], f[u][v] + 1); + } } + } - printf("%d\n", f[0][0] == N ? -1 : f[0][0]); + printf("%d\n", f[0][0] == N ? -1 : f[0][0]); - return 0; + return 0; } - ``` \ No newline at end of file + ```