RT,做法:对于第一个串建 SAM,第二个串去匹配,对每个右端点 i 找到最靠右的左端点 fi 使得 [fi,i] 在第一个串中只出现一次,不存在的话就设成极大值。然后对第二个串建 SAM,也用第二个串去匹配。对所有 fi 取个 min 即可。
好像和第一篇 sam 题解差不多,但不知道哪里写挂了/kk
#include <bits/stdc++.h>
#pragma GCC optimize(3)
//#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
#define vi vector<int>
#define vpi vector<pair<int,int>>
using namespace std; const int N=10010;
inline int read()
{
int s=0, w=1; ri char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
return s*w;
}
char s[N],t[N];
int n,m,F[N],siz[N];
int head[N],maxE; struct Edge { int nxt,to; }e[N];
inline void Add(int u,int v) { e[++maxE].nxt=head[u]; head[u]=maxE; e[maxE].to=v; }
struct SAM
{
int link[N],len[N],ch[N][26];
int tot,lst;
inline SAM() { tot=lst=1; link[1]=len[1]=0; memset(ch[1],0,sizeof(ch[1])); }
inline void Extend(int c)
{
int now=++tot;
int p=lst;
siz[now]=1;
while(p && !ch[p][c]) ch[p][c]=now, p=link[p];
len[now]=len[lst]+1;
if(!p) { lst=now, link[now]=1; return; }
int q=ch[p][c];
if(len[q]==len[p]+1) link[now]=q;
else
{
int nq=++tot;
len[nq]=len[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
link[nq]=link[q];
link[q]=link[now]=nq;
while(p && ch[p][c]==q) ch[p][c]=nq, p=link[p];
}
lst=now;
}
inline void Renew()
{
for(ri int i=1;i<=tot;i++) link[i]=len[i]=siz[i]=head[i]=0, memset(ch[i],0,sizeof(ch[i]));
tot=lst=1; maxE=0;
}
}A;
void DFS(int x)
{
for(ri int i=head[x];i;i=e[i].nxt)
{
int v=e[i].to;
DFS(v);
siz[x]+=siz[v];
}
}
signed main()
{
scanf("%s",s+1);
n=strlen(s+1);
scanf("%s",t+1);
m=strlen(t+1);
for(ri int i=1;i<=n;i++) A.Extend(s[i]-'a');
for(ri int i=2;i<=A.tot;i++) Add(A.link[i],i);
DFS(1);
int sta=1,now=0;
for(ri int i=1;i<=m;i++)
{
int p=t[i]-'a';
while(sta && !A.ch[sta][p]) sta=A.link[sta], now=A.len[sta];
if(!sta) { sta=1, F[i]=1e9; continue; }
if(A.ch[sta][p]) sta=A.ch[sta][p], now++;
int lst=sta;
while(sta && siz[sta]==1) lst=sta, sta=A.link[sta], now=A.len[sta]+1;
sta=lst;
if(siz[sta]==1) F[i]=now;
else F[i]=1e9;
}
A.Renew();
for(ri int i=1;i<=m;i++) A.Extend(t[i]-'a');
for(ri int i=2;i<=A.tot;i++) Add(A.link[i],i);
DFS(1);
sta=1, now=0;
for(ri int i=1;i<=m;i++)
{
int p=t[i]-'a';
while(sta && !A.ch[sta][p]) sta=A.link[sta], now=A.len[sta];
if(!sta) { sta=1, F[i]=1e9; continue; }
if(A.ch[sta][p]) sta=A.ch[sta][p], now++;
int lst=sta;
while(sta && siz[sta]==1) lst=sta, sta=A.link[sta], now=A.len[sta]+1;
sta=lst;
if(siz[sta]==1) F[i]=max(F[i],now);
else F[i]=1e9;
}
int ans=1e9;
for(ri int i=1;i<=m;i++) ans=min(ans,F[i]);
printf("%d\n",(ans>=1e9)?(-1):ans);
return 0;
}