BZOJ 4032: [HEOI2015]最短不公共子串

一:对B串建后缀自动机,暴力枚举A子串的起始位置,匹配不上则更新答案
二:对B串建序列自动机,暴力枚举A子串的起始位置,匹配不上则更新答案
三:对B串建后缀自动机,\(f_{i,j}\) 为考虑A串前 \(i\) 个字符,当前在B串的SAM上的状态为 \(j\) 的最小值,进行DP
四:对B串建序列自动机,\(f_{i,j}\) 为考虑A串前 \(i\) 个字符,当前在B串的 \(j\) 位置的最小值,进行DP

#include <bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define pii pair<int, int>
#define pli pair<ll, int>
#define SZ(x) ((int)(x).size())
#define lp p << 1
#define rp p << 1 | 1
#define mid ((l + r) / 2)
#define lowbit(i) ((i) & (-i))
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
#define rep(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=((b)-1);i>=(a);i--)
#define Edg int ccnt=1,head[N],to[E],ne[E];void addd(int u,int v){to[++ccnt]=v;ne[ccnt]=head[u];head[u]=ccnt;}void add(int u,int v){addd(u,v);addd(v,u);}
#define Edgc int ccnt=1,head[N],to[E],ne[E],c[E];void addd(int u,int v,int w){to[++ccnt]=v;ne[ccnt]=head[u];c[ccnt]=w;head[u]=ccnt;}void add(int u,int v,int w){addd(u,v,w);addd(v,u,w);}
#define es(u,i,v) for(int i=head[u],v=to[i];i;i=ne[i],v=to[i])
const int MOD = 1000000007, INF = 0x3f3f3f3f;
const ll inf = 0x3f3f3f3f3f3f3f3f;
void M(int &x) {if (x >= MOD)x -= MOD; if (x < 0)x += MOD;}
int qp(int a, int b = MOD - 2, int mod = MOD) {int ans = 1; for (; b; a = 1LL * a * a % mod, b >>= 1)if (b & 1)ans = 1LL * ans * a % mod; return ans % mod;}
template<class T>T gcd(T a, T b) { while (b) { a %= b; std::swap(a, b); } return a; }
template<class T>bool chkmin(T &a, T b) { return a > b ? a = b, 1 : 0; }
template<class T>bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }

const int N = 5e3 + 7;
int ch[N][26], len[N], fail[N], sz[N], n, m;
int last, tol;
void init() {
	len[tol = last = 0] = 0; fail[0] = -1;
	rep (i, 0, 26) ch[0][i] = 0;
	tol++;
}
int newnode() {
	int p = tol++;
	rep (i, 0, 26) ch[p][i] = 0;
	len[p] = fail[p] = sz[p] = 0;
	return p;
}
void extend(int c) {
	int cur = newnode();
	len[cur] = len[last] + 1;
	sz[cur] = 1;
	int p = last;
	while (p != -1 && !ch[p][c]) {
		ch[p][c] = cur;
		p = fail[p];
	}
	if (p == -1) {
		fail[cur] = 0;
	} else {
		int q = ch[p][c];
		if (len[p] + 1 == len[q]) {
			fail[cur] = q;
		} else {
			int clone = newnode();
			len[clone] = len[p] + 1;
			memcpy(ch[clone], ch[q], sizeof(ch[q]));
			fail[clone] = fail[q];
			while (p != -1 && ch[p][c] == q) {
				ch[p][c] = clone;
				p = fail[p];
			}
			fail[q] = fail[cur] = clone;
		}
	}
	last = cur;
}
char A[N], B[N];
int pos[26], ne[N][26], f[N][N];

int main() {
#ifdef LOCAL
	freopen("ans.out", "w", stdout);
#endif
	scanf("%s%s", A + 1, B + 1);
	n = strlen(A + 1), m = strlen(B + 1);
	init();
	rep (i, 1, m + 1) extend(B[i] - 'a');
	int ans = N;
	rep (i, 1, n + 1) {
		int cur = 0;
		rep (j, i, n + 1) {
			if (j - i + 1 > ans) break;
			int d = A[j] - 'a';
			if (!ch[cur][d]) chkmin(ans, j - i + 1);
			else cur = ch[cur][d];
		}
	}
	printf("%d\n", ans == N ? -1 : ans);
	rep (i, 0, 26) pos[i] = m + 1;
	per (i, 0, m + 1) {
		rep (j, 0, 26) ne[i][j] = pos[j];
		pos[B[i] - 'a'] = i;
	}
	ans = N;
	rep (i, 1, n + 1) {
		int cur = 0;
		rep (j, i, n + 1) {
			if (j - i + 1 > ans) break;
			int d = A[j] - 'a';
			if (!ne[cur][d] || ne[cur][d] > m) chkmin(ans, j - i + 1);
			else cur = ne[cur][d];
		}
	}
	printf("%d\n", ans == N ? -1 : ans);
	ans = N;
	rep (i, 0, n + 1) rep (j, 0, tol) f[i][j] = N;
	f[0][0] = 0;
	rep (i, 0, n) rep (j, 0, tol) if (f[i][j] < N) {
		chkmin(f[i + 1][j], f[i][j]);
		if (ch[j][A[i + 1] - 'a']) chkmin(f[i + 1][ch[j][A[i + 1] - 'a']], f[i][j] + 1);
		else chkmin(ans, f[i][j] + 1);
	}
	printf("%d\n", ans == N ? -1 : ans);
	ans = N;
	rep (i, 0, n + 1) rep (j, 0, tol) f[i][j] = N;
	f[0][0] = 0;
	rep (i, 0, n) rep (j, 0, m + 1) if (f[i][j] < N) {
		chkmin(f[i + 1][j], f[i][j]);
		if (ne[j][A[i + 1] - 'a'] <= m) chkmin(f[i + 1][ne[j][A[i + 1] - 'a']], f[i][j] + 1);
		else chkmin(ans, f[i][j] + 1);
	}
	printf("%d\n", ans == N ? -1 : ans);
#ifdef LOCAL
	printf("%.10f\n", (db)clock() / CLOCKS_PER_SEC);
#endif
	return 0;
}
posted @ 2020-03-18 19:03  Mrzdtz220  阅读(106)  评论(0编辑  收藏  举报