序列自动机就是可以识别所有子序列的自动机,点数
O(n)
,边数
O(26n)
每个点的par就是这个点代表的字母上一次出现的位置,因此要记录last[i],表示字母i上一次出现在哪,然后每一个点的儿子i指向他后面出现的第一个字母i的位置。
求A最短的子串/子序列不是B的子串/子序列,我们两个自动机一起跑,状态[x][y]表示一个字符串匹配到了A自动机的x节点,B自动机的y节点,因为是bfs,可以发现此时的字符串是符合状态的最短的。如果A匹配上了,而B没匹配上,就是答案了。
复杂度 O(26n2)
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <utility>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 2010
#define pa pair<pair<int,int>,int>
int m;
char s[N];bool vis[N<<1][N<<1];
struct SAM{
int n,son[N<<1][26],par[N<<1],mx[N<<1],rt,last;
inline void init(){n=0;last=rt=++n;}
inline void ins(int ch){
int p=last,np=++n;mx[np]=mx[p]+1;last=np;
for(;p&&!son[p][ch];p=par[p]) son[p][ch]=np;
if(!p){par[np]=rt;return;}
int q=son[p][ch];
if(mx[q]==mx[p]+1){par[np]=q;return;}
int nq=++n;mx[nq]=mx[p]+1;memcpy(son[nq],son[q],sizeof(son[q]));
par[nq]=par[q];par[q]=par[np]=nq;
for(;p&&son[p][ch]==q;p=par[p]) son[p][ch]=nq;
}
}A,B;
struct SEAM{
int n,son[N][26],par[N],last[26],rt;
inline void init(){n=0;rt=++n;for(int i=0;i<26;++i) last[i]=rt;}
inline void ins(int ch){
int np=++n;
for(int i=0;i<26;++i)
for(int p=last[i];p&&!son[p][ch];p=par[p]) son[p][ch]=np;
par[np]=last[ch];last[ch]=np;
}
}AE,BE;
inline int bfs1(){
queue<pa>q;memset(vis,0,sizeof(vis));
q.push(make_pair(make_pair(A.rt,B.rt),0));vis[A.rt][B.rt]=1;
while(!q.empty()){
int x=q.front().first.first,y=q.front().first.second,z=q.front().second;q.pop();
for(int i=0;i<26;++i){
int xx=A.son[x][i],yy=B.son[y][i];
if(!xx) continue;if(!yy) return z+1;
if(vis[xx][yy]) continue;vis[xx][yy]=1;
q.push(make_pair(make_pair(xx,yy),z+1));
}
}return -1;
}
inline int bfs2(){
queue<pa>q;memset(vis,0,sizeof(vis));
q.push(make_pair(make_pair(A.rt,BE.rt),0));vis[A.rt][BE.rt]=1;
while(!q.empty()){
int x=q.front().first.first,y=q.front().first.second,z=q.front().second;q.pop();
for(int i=0;i<26;++i){
int xx=A.son[x][i],yy=BE.son[y][i];
if(!xx) continue;if(!yy) return z+1;
if(vis[xx][yy]) continue;vis[xx][yy]=1;
q.push(make_pair(make_pair(xx,yy),z+1));
}
}return -1;
}
inline int bfs3(){
queue<pa>q;memset(vis,0,sizeof(vis));
q.push(make_pair(make_pair(AE.rt,B.rt),0));vis[AE.rt][B.rt]=1;
while(!q.empty()){
int x=q.front().first.first,y=q.front().first.second,z=q.front().second;q.pop();
for(int i=0;i<26;++i){
int xx=AE.son[x][i],yy=B.son[y][i];
if(!xx) continue;if(!yy) return z+1;
if(vis[xx][yy]) continue;vis[xx][yy]=1;
q.push(make_pair(make_pair(xx,yy),z+1));
}
}return -1;
}
inline int bfs4(){
queue<pa>q;memset(vis,0,sizeof(vis));
q.push(make_pair(make_pair(AE.rt,BE.rt),0));vis[AE.rt][BE.rt]=1;
while(!q.empty()){
int x=q.front().first.first,y=q.front().first.second,z=q.front().second;q.pop();
for(int i=0;i<26;++i){
int xx=AE.son[x][i],yy=BE.son[y][i];
if(!xx) continue;if(!yy) return z+1;
if(vis[xx][yy]) continue;vis[xx][yy]=1;
q.push(make_pair(make_pair(xx,yy),z+1));
}
}return -1;
}
int main(){
// freopen("a.in","r",stdin);
scanf("%s",s+1);m=strlen(s+1);A.init();AE.init();
for(int i=1;i<=m;++i) A.ins(s[i]-'a'),AE.ins(s[i]-'a');
scanf("%s",s+1);m=strlen(s+1);B.init();BE.init();
for(int i=1;i<=m;++i) B.ins(s[i]-'a'),BE.ins(s[i]-'a');
printf("%d\n",bfs1());printf("%d\n",bfs2());
printf("%d\n",bfs3());printf("%d\n",bfs4());
return 0;
}