建出A串B串的SAM
第一个询问可以直接暴力在SAM上跑所有子串..
第二个询问…好像也可以暴力跑所有子串..
第三个询问,用状态(i,j,t)表示当前在A串的i位置,B串SAM的j节点,子序列长度为t,每次枚举26个字母转移,把新状态塞进堆里
第四个询问,f[i][j]表示当前子序列结尾在A串是i,B串是j,最短长度
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#define ll long long
using namespace std;
inline void down(int &x,const int y){if(x>y)x=y;}
const int maxn = 2100;
struct SAM
{
int son[26],par;
int v;
SAM(){}
SAM(const int _v){v=_v;par=0; memset(son,0,sizeof son);}
}sam[2][maxn<<1]; int root[2],last[2],tot[2];
void extend(SAM sam[],const int now,const int w)
{
int p=last[now],np;
sam[np=++tot[now]]=SAM(sam[p].v+1);
while(p&&!sam[p].son[w])
sam[p].son[w]=np,p=sam[p].par;
if(!p) sam[np].par=root[now];
else
{
int q=sam[p].son[w];
if(sam[q].v==sam[p].v+1) sam[np].par=q;
else
{
int nq; sam[nq=++tot[now]]=SAM(sam[p].v+1);
memcpy(sam[nq].son,sam[q].son,sizeof sam[q].son);
sam[nq].par=sam[q].par;
sam[q].par=nq;
sam[np].par=nq;
while(p&&sam[p].son[w]==q)
sam[p].son[w]=nq,p=sam[p].par;
}
}
last[now]=np;
}
char A[maxn],B[maxn];
int alen,blen;
int nex[2][maxn][26];
int las[26];
struct node
{
int x,y,v;
node(){}
node(const int _x,const int _y,const int _v){x=_x;y=_y;v=_v;}
};
queue<node>q;
int solve1()
{
int re=-1;
q.push(node(root[0],root[1],0));
while(!q.empty())
{
const node x=q.front(); q.pop();
const int p=x.x,y=x.y;
for(int j=0;j<26;j++) if(sam[0][p].son[j])
{
if(!sam[1][y].son[j])
{
re=x.v+1;
break;
}
else q.push(node(sam[0][p].son[j],sam[1][y].son[j],x.v+1));
}
if(re!=-1) break;
}
while(!q.empty())q.pop();
return re;
}
int solve2()
{
int re=-1;
q.push(node(root[0],blen,0));
while(!q.empty())
{
const node x=q.front(); q.pop();
const int p=x.x,y=x.y;
for(int j=0;j<26;j++) if(sam[0][p].son[j])
{
if(nex[1][y][j]>=blen)
{
re=x.v+1;
break;
}
else q.push(node(sam[0][p].son[j],nex[1][y][j],x.v+1));
}
if(re!=-1) break;
}
while(!q.empty()) q.pop();
return re;
}
int solve3()
{
int re=-1;
q.push(node(alen,root[1],0));
while(!q.empty())
{
const node x=q.front(); q.pop();
const int p=x.x,y=x.y;
for(int j=0;j<26;j++) if(nex[0][p][j]<alen)
{
if(!sam[1][y].son[j])
{
re=x.v+1;
break;
}
else q.push(node(nex[0][p][j],sam[1][y].son[j],x.v+1));
}
if(re!=-1) break;
}
while(!q.empty()) q.pop();
return re;
}
int f[maxn][maxn];
int solve4()
{
memset(f,-1,sizeof f);
for(int j=0;j<26;j++) if(nex[0][alen][j]<alen)
{
if(nex[1][blen][j]>=blen) return 1;
else f[nex[0][alen][j]][nex[1][blen][j]]=1;
}
int re=alen+1;
for(int i=0;i<alen;i++)
{
for(int j=0;j<blen;j++) if(f[i][j]!=-1)
{
const int v=f[i][j]+1;
for(int l=0;l<26;l++) if(nex[0][i][l]<alen)
{
if(nex[1][j][l]>=blen) down(re,v);
int t1=nex[0][i][l],t2=nex[1][j][l];
if(f[t1][t2]>v||f[t1][t2]==-1) f[t1][t2]=v;
}
}
}
if(re==alen+1) re=-1;
return re;
}
int main()
{
tot[0]=tot[1]=1; root[0]=root[1]=last[0]=last[1]=1;
scanf("%s%s",A,B);
alen=strlen(A); blen=strlen(B);
for(int i=0;i<alen;i++) extend(sam[0],0,A[i]-'a');
for(int i=0;i<blen;i++) extend(sam[1],1,B[i]-'a');
//A:
for(int i=0;i<26;i++) las[i]=alen;
for(int i=alen-1;i>=0;i--)
{
for(int j=0;j<26;j++) nex[0][i][j]=las[j];
const int w=A[i]-'a';
las[w]=i;
}
for(int j=0;j<26;j++) nex[0][alen][j]=las[j];
//B:
for(int i=0;i<26;i++) las[i]=blen;
for(int i=blen-1;i>=0;i--)
{
for(int j=0;j<26;j++) nex[1][i][j]=las[j];
const int w=B[i]-'a';
las[w]=i;
}
for(int j=0;j<26;j++) nex[1][blen][j]=las[j];
printf("%d\n",solve1());
printf("%d\n",solve2());
printf("%d\n",solve3());
printf("%d\n",solve4());
return 0;
}