【LOJ】#2123. 「HEOI2015」最短不公共子串

题解

我们对于B串建出后缀自动机和序列自动机
对于问题1,枚举左端点然后跑后缀自动机,直到不能匹配作为这个左端点的答案
对于问题2,枚举左端点然后跑序列自动机,直到不能匹配

对于问题3,设f[i][j]表示第前i个字符匹配到后缀自动机上第j个点的最少步数,如果下一步走不了则更新答案
对于问题4,设f[i][j]表示前i个字符匹配到序列自动机上第j个点的最少步数,如果下一步走不了则更新答案

代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#define enter putchar('\n')
#define space putchar(' ')
//#define ivorysi
using namespace std;
typedef long long int64;
template<class T>
void read(T &res) {
	res = 0;char c = getchar();T f = 1;
	while(c < '0' || c > '9') {
		if(c == '-') f = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9') {
		res = res * 10 + c - '0';
		c = getchar();
	}
	res *= f;
}
template<class T>
void out(T x) {
	if(x < 0) {putchar('-');x = -x;}
	if(x >= 10) {
		out(x / 10);
	}
	putchar('0' + x % 10);
}
const int MOD = 1000000007;
char A[2005],B[2005];
int LA,LB;
int f[2005][4005];
struct SuffixAutoMaton{
	struct SAM_node {
		SAM_node *par,*nxt[26];
		int len;
		SAM_node *find_next(char c) {
			if(nxt[c - 'a']) return nxt[c - 'a'];
			else return NULL;
		}
	}pool[4005],*tail = pool,*root,*last;
	SuffixAutoMaton() {
		root = last = tail++;
	}
	void build(int l,int e) {
		SAM_node *nowp = tail++,*p;
		nowp->len = l;
		for(p = last ; p && !p->nxt[e]; p = p->par) {
			p->nxt[e] = nowp;
		}
		if(!p) nowp->par = root;
		else {
			SAM_node *q = p->nxt[e];
			if(q->len == p->len + 1) nowp->par = q;
			else {
				SAM_node *copyq = tail++;
				*copyq = *q;
				copyq->len = p->len + 1;
				q->par = nowp->par = copyq;
				for( ; p && p->nxt[e] == q ; p = p->par) {
					p->nxt[e] = copyq;
				}
			}
		}
		last = nowp;
	}
	int calc1(int st) {
		SAM_node *p = root;
		int res = 0;
		for(int i = st ; i <= LA ; ++i) {
			p = p->find_next(A[i]);
			if(!p) break;
			++res;
		}
		if(res == LA - st + 1) return LA + 1;
		return res + 1;
	}
	int calc3() {
		int m = tail - pool;
		for(int i = 0 ; i <= LA ; ++i) {
			for(int j = 1 ; j <= m ; ++j) {
				f[i][j] = 0x7fffffff;
			}
		}
		f[0][1] = 0;
		int res = LA + 1;
		for(int i = 1 ; i <= LA ; ++i) {
			for(int j = 1 ; j <= m ; ++j) {
				if(f[i - 1][j] != 0x7fffffff) {
					f[i][j] = min(f[i - 1][j],f[i][j]);
					SAM_node *p = pool[j - 1].find_next(A[i]);
					if(!p) res = min(res,f[i - 1][j] + 1);
					else f[i][p - pool + 1]  = min(f[i][p - pool + 1],f[i][j] + 1);
				}
			}
		}
		return res;
	}
}SAM;
struct LineAutoMaton {
	int ch[2005][26],head[30],next[2005],tot,rt;
	LineAutoMaton() {
		rt = tot = 1;
		for(int i = 0 ; i < 26 ; ++i) head[i] = 1;
	}
	void build(char c) {
		++tot;next[tot] = head[c - 'a'];
		for(int i = 0 ; i < 26 ; ++i) {
			for(int j = head[i] ; j ; j = next[j]) {
				if(!ch[j][c - 'a']) ch[j][c - 'a'] = tot;
				else break;
			}
		}
		head[c - 'a'] = tot;
	}
	int calc2(int st) {
		int p = rt,L = 0;
		for(int i = st ; i <= LA ; ++i) {
			if(ch[p][A[i] - 'a']) {
				p = ch[p][A[i] - 'a'];
				++L;
			}
			else break;
		}
		if(L == LA - st + 1) return LA + 1;
		return L + 1;
	}
	int calc4() {
		for(int i = 0 ;i <= LA ; ++i) {
			for(int j = 1 ; j <= tot ; ++j) {
				f[i][j] = 0x7fffffff;
			}
		}
		f[0][1] = 0;
		int res = LA + 1;
		for(int i = 1 ; i <= LA ; ++i) {
			for(int j = 1 ; j <= tot ; ++j) {
				if(f[i - 1][j] != 0x7fffffff) {
					f[i][j] = min(f[i - 1][j],f[i][j]);
					int p = ch[j][A[i] - 'a'];
					if(!p) res = min(res,f[i - 1][j] + 1);
					else f[i][p] = min(f[i - 1][j] + 1,f[i][p]); 
				}
			}
		}
		return res;
	}	
}LAM;
void Init() {
	scanf("%s",A + 1);
	scanf("%s",B + 1);
	LA = strlen(A + 1);LB = strlen(B + 1);
	for(int i = 1 ; i <= LB ; ++i) {
		SAM.build(i,B[i] - 'a');
		LAM.build(B[i]);
	}
}
void Solve1() {
	int ans = LA + 1;
	for(int i = 1 ; i <= LA ; ++i) {
		ans = min(ans,SAM.calc1(i));
	}
	if(ans > LA) puts("-1");
	else {out(ans),enter;}
}
void Solve2() {
	int ans = LA + 1;
	for(int i = 1 ; i <= LA ; ++i) {
		ans = min(ans,LAM.calc2(i));
	}
	if(ans > LA) puts("-1");
	else out(ans),enter;
}
void Solve3() {
	int ans = SAM.calc3();
	if(ans > LA) puts("-1");
	else out(ans),enter;
}
void Solve4() {
	int ans = LAM.calc4();
	if(ans > LA) puts("-1");
	else out(ans),enter;
}
int main() {
#ifdef ivorysi
	freopen("f1.in","r",stdin);
#endif
	Init();
	Solve1();
	Solve2();
	Solve3();
	Solve4();
}
posted @ 2018-06-15 20:52  sigongzi  阅读(367)  评论(0编辑  收藏  举报