LG P4112 [HEOI2015]最短不公共子串(后缀自动机 + 序列自动机)

版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/qq_35950004/article/details/88865841

题目
我刚写完占坑就让我打这玩意。
天道有轮回,苍天饶过谁。。。。。。
首先这个题,你得知道后缀自动机是一个DAG,所有子串都可以用这个DAG表示出来。
然后这个题,你得知道序列自动机也是个DAG,所有子序列都能用这个DAG表示出来。
然后就在这个DAG上BFS找最浅的在第一个DAG上合法,在第二个DAG上非法的点就行了。
以为是字典序最小,打DFS ,1WA
打BFS开 i n t [ 4005 ] [ 4005 ] int[4005][4005] , MLE
又打回DFS搜完,TLE
加一发 m a p map 记忆化,WA???
原来到DAG上同样的两个点的距离会不一样啊。
m a p map 存了一个奇怪的东西,AC
NOIP选手表示。。。。。
AC Code:

#include<bits/stdc++.h>
#define maxn 4005
#define maxc 26
#define inf 0x3f3f3f3f
using namespace std;

int last,n,m;
int tr[4][maxn][maxc],fail[2][maxn],len[2][maxn],tot[2],nxt[maxc];
char A[maxn],B[maxn];

void ins(int c,int tr[maxn][maxc],int fail[maxn],int len[maxn],int &tot){
	int p = last , q , cur = ++ tot;
	len[last = cur] = len[p] + 1;
	for(;p!=-1 && tr[p][c]==-1;p=fail[p]) tr[p][c]=cur;
	if(p==-1) fail[cur] = 0;
	else if(len[q=tr[p][c]] == len[p] + 1) fail[cur] = q;
	else {
		int cln = ++tot;
		memcpy(tr[cln],tr[q],sizeof tr[q]),len[cln] = len[p] + 1;
		for(;p!=-1 && tr[p][c]==q;p=fail[p]) tr[p][c] = cln;
		fail[cln] = fail[q] , fail[q] = fail[cur] = cln;
	}
}

map<int,int>mp[4][maxn];
int flag = 0;
int dfs(int rt1,int rt2,int tr[maxn][maxc],int tr2[maxn][maxc],int len,int tp){
	if(rt1==-1) return inf;
	if(rt2==-1) return len; 
	if(mp[tp][rt1].count(rt2)) return len+mp[tp][rt1][rt2];
	int ret = inf;
	for(int i=0;i<maxc;i++)
		ret = min(ret , dfs(tr[rt1][i],tr2[rt2][i],tr,tr2,len+1,tp));
	mp[tp][rt1][rt2] = ret - len;
	return ret;
}

int main(){
	//freopen("1.in","r",stdin);
	//freopen("1.out","w",stdout);
	scanf("%s",A);scanf("%s",B);
	memset(tr,-1,sizeof tr);
	n = strlen(A) , m = strlen(B);
	fail[0][0] = fail[1][0] = -1;
	for(int i=0;i<n;i++) ins(A[i]-'a',tr[0],fail[0],len[0],tot[0]);
	last = 0;
	for(int i=0;i<m;i++) ins(B[i]-'a',tr[1],fail[1],len[1],tot[1]);
	memset(nxt,-1,sizeof nxt);
	for(int i=n;i>=1;i--){
		memcpy(tr[2][i],nxt,sizeof nxt);
		nxt[A[i-1]-'a'] = i;
	}
	memcpy(tr[2][0],nxt,sizeof nxt);
	memset(nxt,-1,sizeof nxt);
	for(int i=m;i>=1;i--){
		memcpy(tr[3][i],nxt,sizeof nxt);
		nxt[B[i-1]-'a'] = i;
	}
	memcpy(tr[3][0],nxt,sizeof nxt);
	
	int tmp;
	printf("%d\n",(tmp=dfs(0,0,tr[0],tr[1],0,0)) == inf ? -1 : tmp);
	printf("%d\n",(tmp=dfs(0,0,tr[0],tr[3],0,1)) == inf ? -1 : tmp);
	printf("%d\n",(tmp=dfs(0,0,tr[2],tr[1],0,2)) == inf ? -1 : tmp);
	printf("%d\n",(tmp=dfs(0,0,tr[2],tr[3],0,3)) == inf ? -1 : tmp);
}

猜你喜欢

转载自blog.csdn.net/qq_35950004/article/details/88865841
今日推荐