题目大意:有$n$个字符串,求这$n$个字符串中最长的相似公共字串,相似的定义是加上一个数后相同
题解:差分,建广义后缀自动机,然后求出每个点在多少个字符串中出现过,若在$n$个中都出现,就更新答案
卡点:无
C++ Code:
#include <cstdio> #include <map> #include <vector> #define maxn 1010 std::vector<int> s[maxn]; namespace SAM { #define N (maxn * 100 << 1) int R[N], fail[N]; std::map<int, int> nxt[N]; int idx = 1, lst = 1; void append(int ch) { int p = lst, np = lst = ++idx; R[np] = R[p] + 1; for (; p && !nxt[p].count(ch); p = fail[p]) nxt[p][ch] = np; if (!p) fail[np] = 1; else { int q = nxt[p][ch]; if (R[p] + 1 == R[q]) fail[np] = q; else { int nq = ++idx; R[nq] = R[p] + 1; fail[nq] = fail[q], fail[q] = fail[np] = nq; nxt[nq] = nxt[q]; for (; p && nxt[p].count(ch) && nxt[p][ch] == q; p = fail[p]) nxt[p][ch] = nq; } } } int bel[N], cnt[N]; void jmp(int p, int tg) { for (; bel[p] != tg; p = fail[p]) bel[p] = tg, cnt[p]++; } void work(int i) { int p = 1; for (std::vector<int>::iterator it = s[i].begin(); it != s[i].end(); ++it) jmp(p = nxt[p][*it], i); } int query(int n) { int res = 0; for (int i = 1; i <= idx; i++) if (cnt[i] == n) { res = std::max(res, R[i] + 1); } return res; } #undef N } int n; int main() { scanf("%d", &n); for (int i = 1, lst, x, m; i <= n; i++) { scanf("%d%d", &m, &lst); SAM::lst = 1; for (int j = 1; j < m; j++) { scanf("%d", &x); SAM::append(x - lst); s[i].push_back(x - lst); lst = x; } } for (int i = 1; i <= n; i++) SAM::work(i); printf("%d ", SAM::query(n)); return 0; }