做法千万万
对串 A # B A\#B A#B建立 S A M SAM SAM
如果是插入第一个串产生的节点标记为 1 1 1,插入第二个串产生的节点标记为 2 2 2
维护一下每个 e n d p o s endpos endpos出现几次,发现答案一定是那些出现次数为 2 2 2的节点
因为只在两个串中出现一次,而且一定不包含 # \# #,包含 # \# #的子串只会出现一次
那如何判断这个 e n d p o s endpos endpos类是在一个串中出现两次,还是分别在两个串中出现一次呢
如果是分别在两个串中出现一次,那这个节点一定是由串 A A A新建的
然后插入串 B B B的时候,也出现过这个 e n d p o s endpos endpos,所以会把后缀链接指向这个 e n d p o s endpos endpos
那我们只需要拓扑排序推标记即可
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10;
char a[maxn],b[maxn];
int zi[maxn][33],len[maxn],fa[maxn],mark[maxn],siz[maxn],ed=1,id=1;
void add(int c,int x)
{
int p = ed, np = ++id; ed = id;
mark[np] = x, len[np] = len[p]+1; siz[np] = 1;
for( ; p && !zi[p][c]; p = fa[p] ) zi[p][c] = np;
if( p==0 ) fa[np] = 1;
else
{
int q = zi[p][c];
if( len[q]==len[p]+1 ) fa[np] = q;
else
{
int nq = ++id;
memcpy( zi[nq],zi[q],sizeof zi[nq] );
fa[nq] = fa[q], len[nq] = len[p]+1, mark[nq] = mark[q];
fa[np] = fa[q] = nq;
for( ;p&&zi[p][c]==q;p=fa[p] ) zi[p][c] = nq;
}
}
}
int c[maxn],rk[maxn],ans=1e9;
void chiken_sort()
{
for(int i=1;i<=id;i++) c[len[i]]++;
for(int i=1;i<=id;i++) c[i] += c[i-1];
for(int i=1;i<=id;i++) rk[c[len[i]]--] = i;
for(int i=id;i>=1;i--)
{
int u = rk[i];
siz[fa[u]] += siz[u]; mark[fa[u]] |= mark[u];
if( siz[u]==2&&mark[u]==3 ) ans = min( ans,len[fa[u]]+1 );
}
}
int main()
{
cin >> ( a+1 ) >> ( b+1 );
int len1 = strlen( a+1 ), len2 = strlen( b+1 );
for(int i=1;i<=len1;i++) add( a[i]-'a',1 );
add( 26,1 );
for(int i=1;i<=len2;i++) add( b[i]-'a',2 );
chiken_sort();
if( ans==1e9 ) cout << -1;
else cout << ans;
}