题意:
给你两个字符串,让你求出这两个字符串的最短公共子串,且这个子串在这两个字符串中都只出现过一次
题解:
对这两个串分别建SAM,然后dfs跑相同边判断即可。
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e4+50;
const int INF = 0x3f3f3f3f;
struct Suffix{
int nxt[MAXN][26],fa[MAXN],len[MAXN];
int c[MAXN],a[MAXN],cnt[MAXN];
int last=1,tot=1;
inline void Insert(int x){
int p=last,np=++tot;
last=np,len[np]=len[p]+1;
for(;p&&!nxt[p][x];p=fa[p]) nxt[p][x]=np;
if(!p) fa[np]=1;
else{
int q = nxt[p][x];
if(len[p]+1==len[q]) fa[np]=q;
else{
int nq = ++tot;
len[nq]=len[p]+1;
memcpy(nxt[nq],nxt[q],sizeof(nxt[q]));
fa[nq]=fa[q];
fa[q]=fa[np]=nq;
for(;nxt[p][x]==q;p=fa[p]) nxt[p][x]=nq;
}
}
cnt[np]=1;
}
inline void Sort(){
for(int i=1;i<=tot;i++) c[len[i]]++;
for(int i=1;i<=tot;i++) c[i]+=c[i-1];
for(int i=tot;i;i--) a[c[len[i]]--]=i;
for(int i=tot;i;i--) cnt[fa[a[i]]] += cnt[a[i]];
}
}SAM1,SAM2;
char s[MAXN],t[MAXN];
int res = INF;
void dfs(int u1,int u2,int deep){
for(int i=0;i<26;i++){
if(SAM1.nxt[u1][i] && SAM2.nxt[u2][i]){
if(SAM1.cnt[SAM1.nxt[u1][i]]==1 && SAM2.cnt[SAM2.nxt[u2][i]]==1){
res = min(res,deep);
return;
}
dfs(SAM1.nxt[u1][i],SAM2.nxt[u2][i],deep+1);
}
}
}
int main(){
scanf("%s%s",s,t);
int ls=strlen(s),lt=strlen(t);
for(int i=0;i<ls;i++) SAM1.Insert(s[i]-'a');
for(int i=0;i<lt;i++) SAM2.Insert(t[i]-'a');
SAM1.Sort(); SAM2.Sort();
dfs(1,1,1);
cout<<(res == INF ? -1:res)<<endl;
return 0;
}