题意是说,给定两个字符串,找到最小的相同串,同时这个串只能在两个串中出现一次。开始想可能是后缀数组,但是不太会,参考了一下别人的想法,发现字符串hash也可以做。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef unsigned __int64 ULL;
const int Maxn=6000;
const ULL seed=13331,length=10007;
struct node
{
ULL val;
int next;
node(){};
node(ULL v,int n) : val(v), next(n){};
};
ULL seedpow[Maxn] = {1ULL}, hash1[Maxn], hash2[Maxn];
node edge[Maxn<<1];
int head[length], cnt1[Maxn<<1], cnt2[Maxn<<1], sz;
char s[Maxn], t[Maxn];
void insert(ULL w,bool flag)
{
int p=w%length;
for(int i=head[p];i>=0;i=edge[i].next)
{
if(w!=edge[i].val) continue;
if(flag==true) cnt1[i]++;
else cnt2[i]++;
return ;
}
cnt1[sz]=0;
cnt2[sz]=0;
if(flag) cnt1[sz]++;
else cnt2[sz]++;
edge[sz]=node(w,head[p]);
head[p]=sz++;
return ;
}
int main()
{
scanf("%s%s",&s,&t);
int ls=strlen(s);
int lt=strlen(t);
for(int i=1;i<=max(ls,lt);i++)
{
seedpow[i]=seedpow[i-1]*seed;
}
for(int i=1;i<=ls;i++)
{
hash1[i]=hash1[i-1]*seed+s[i-1];
}
for(int i=1;i<=lt;i++)
{
hash2[i]=hash2[i-1]*seed+t[i-1];
}
for(int l=1;l<=min(ls,lt);l++)
{
for(int i=0;i<length;i++) head[i]=-1;
sz=0;
for(int ed=l;ed<=ls;ed++)
{
insert(hash1[ed]-hash1[ed-l]*seedpow[l],true);
}
for(int ed=l;ed<=lt;ed++)
{
insert(hash2[ed]-hash2[ed-l]*seedpow[l],false);
}
for(int i=0;i<sz;i++)
{
if(cnt1[i]==1&&cnt2[i]==1)
{
printf("%d\n",l);
return 0;
}
}
}
printf("-1\n");
return 0;
}