[BZOJ4032] [HEOI2015] 最短不公共子串 - 后缀自动机,序列自动机,BFS

来源:互联网 发布:模拟核弹爆炸软件 编辑:程序博客网 时间:2024/06/08 12:46

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

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 398  Solved: 189
[Submit][Status][Discuss]

Description

 在虐各种最长公共子串、子序列的题虐的不耐烦了之后,你决定反其道而行之。

一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是。
一个串的“子序列”指的是它的可以不连续的一段,例如bde是abcdef的子串,但bdd不是。
下面,给两个小写字母串A,B,请你计算:
(1) A的一个最短的子串,它不是B的子串
(2) A的一个最短的子串,它不是B的子序列
(3) A的一个最短的子序列,它不是B的子串
(4) A的一个最短的子序列,它不是B的子序列

Input

有两行,每行一个小写字母组成的字符串,分别代表A和B。

Output

输出4行,每行一个整数,表示以上4个问题的答案的长度。如果没有符合要求的答案,输出-1.

Sample Input

aabbcc
abcabc

Sample Output

2
4
2
4

HINT

 对于100%的数据,A和B的长度都不超过2000


Source

[Submit][Status][Discuss]

HOME Back

其实序列自动机就是一个纸张的能遍历出所有子序列的自动机。。其实就是每个点的右边的不同字符的最近出现位置。

那么我们这些询问怎么做呢,首先我们建出每个串的后缀自动机和序列自动机,这样我们就能遍历所有的子序列了。

然后这样第一个询问随便用两个后缀自动机来BFS一下就好了(最简单的询问,trie或者hash都可以)。

那么第二个询问怎么搞呢,这个时候我们就发现一个显然对于4个询问都承认的限制:若用dp[i][j]表示第一个串在自动机上匹配到i位置,第二个串在自动机上匹配到j位置,那么显然dp[i][j]最小。

所以我们只要BFS就可以满足这样的要求。我们对于第二个询问匹配第一个串的后缀自动机(遍历所有子串)和序列自动机(遍历所有子序列),同理我们匹配不同的自动机,可以解决这个问题。

时间复杂度O(n^2*26)

#include"bits/stdc++.h"#define F(i,l,r) for(int i=l;i<=r;i++)#define D(i,r,l) for(int i=r;i>=l;i--)using namespace std;const int N=2005,M=26;char s1[N],s2[N];struct SequenceAutoMaton{int a[N],e[N][M],n,last[M];void pre(char*s){n=strlen(s+1);D(i,n,1){memcpy(e[i+1],last,sizeof(int[M]));a[i]=s[i]-'a';last[a[i]]=i+1;}memcpy(e[1],last,sizeof(int[M]));}} sqa[2];struct SuffixAutoMaton{int a[N*2],e[N*2][M],fail[N*2],d[N*2],last,n,nd;SuffixAutoMaton(){nd=last=1;}void extend(int c){int np=++nd,p=last;d[np]=d[last]+1;for(;!e[p][c]&&p;e[p][c]=np,p=fail[p]);if(!p)fail[np]=1;else {int q=e[p][c],nq;if(d[q]==d[p]+1)fail[np]=q;else {nq=++nd;d[nq]=d[p]+1;memcpy(e[nq],e[q],sizeof(int[M]));fail[nq]=fail[q];fail[np]=fail[q]=nq;for(;e[p][c]==q;e[p][c]=nq,p=fail[p]);}}last=np;}void pre(char*s){n=strlen(s+1);F(i,1,n){a[i]=s[i]-'a';extend(a[i]);}}} sam[2];int dp[2*N][2*N],q1[N*N],q2[N*N],l,r;template<class T1,class T2>void DP(T1&x,T2&y){q1[1]=q2[1]=1;memset(dp,0,sizeof(dp));for(l=r=1;l<=r;l++){F(i,0,25){int dx=x.e[q1[l]][i],dy=y.e[q2[l]][i];if(!dx)continue;if(!dy){printf("%d\n",dp[q1[l]][q2[l]]+1);return;}if(dp[dx][dy])continue;dp[dx][dy]=dp[q1[l]][q2[l]]+1;++r;q1[r]=dx;q2[r]=dy;}}puts("-1");}int main(){scanf("%s\n%s",s1+1,s2+1);sqa[0].pre(s1),sqa[1].pre(s2);sam[0].pre(s1),sam[1].pre(s2);DP(sam[0],sam[1]);DP(sam[0],sqa[1]);DP(sqa[0],sam[1]);DP(sqa[0],sqa[1]); return 0;}


0 0