CF427D Match & Catch
https://www.luogu.com.cn/problem/CF427D
广义SAM板板题
每个节点分别统计两个串的size,(注意,SAM并不是编号越大的节点深度越大,所以必须要一个dfs来统计)
我是另一种写法,不过无所谓了
code:
#include<bits/stdc++.h>
#define N 200050
using namespace std;
struct A {
int ch[27], len, fa;
} a[N << 1];
int lst = 1, tot = 1, size[N][2], n;
void insert(int c, int o) {
int p = lst, np = ++ tot; lst = np;
a[np].len = a[p].len + 1;
while(p && !a[p].ch[c]) a[p].ch[c] = np, p = a[p].fa;
if(!p) a[np].fa = 1;
else {
int q = a[p].ch[c];
if(a[q].len == a[p].len + 1) a[np].fa = q;
else {
int clone = ++ tot; a[clone] = a[q];
a[clone].len = a[p].len + 1; size[clone][0] = size[q][0]; size[clone][1] = size[q][1];
while(p && a[p].ch[c] == q) a[p].ch[c] = clone, p = a[p].fa;
a[q].fa = a[np].fa = clone;
}
}
// printf(" %d *%d %d ", lst, a[7].fa, size[7][o]);
int now = lst;
while(now && size[now][o] <= 1) size[now][o] ++, now = a[now].fa;//, printf("(%d %d) ", now, size[now][o]); printf("\n");
// printf(" %d *%d %d \n", now, a[7].fa, size[7][o]);
}
char st[N], stt[N];
int main() {
scanf("%s", st + 1);
int n = strlen(st + 1);
for(int i = 1; i <= n; i ++) insert(st[i] - 'a', 0);
// for(int i = 1; i <= tot; i ++) printf("%d ", size[i][0]); printf("\n");
scanf(" %s", stt + 1);
n = strlen(stt + 1);
lst = 1;
for(int i = 1; i <= n; i ++) insert(stt[i] - 'a', 1);
// for(int i = 1; i <= tot; i ++) printf("%d ", size[i][0]); printf("\n");
// for(int i = 1; i <= tot; i ++) printf("%d ", size[i][1]); printf("\n");
/* for(int i = tot; i >= 1; i --) {
size[a[i].fa][0] += size[i][0];
size[a[i].fa][1] += size[i][1];
}*/
int ans = n + 1;
for(int i = 2; i <= tot; i ++) {
if(size[i][0] == 1 && size[i][1] == 1) {
ans = min(ans, a[a[i].fa].len + 1);
// printf("%d %d %d\n", i, ans, n);
}
}
if(ans == n + 1) ans = -1;
printf("%d", ans);
return 0;
}