Long Long Message
题意
给出两个字符串,让找出最长的公共子串
思路
把两个字符串合起来,做最长不重叠子串即可。
[poj 1743] Musical Theme 后缀数组 or hash
数组开二倍
代码
/*Gts2m ranks first in the world*/
#define pb push_back
#define stop system("pause")
#include<stdio.h>
#include<string.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<string>
#include<algorithm>
#include<iostream>
// #include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
typedef long long ll;
typedef unsigned long long ull;
char s[N],t[N];
int sa[N],rk[N],oldrk[N],cnt[N],pos[N],ht[N];
int n,m;
bool cmp(int a,int b,int k)
{
return oldrk[a]==oldrk[b]&&oldrk[a+k]==oldrk[b+k];
}
void getsa()
{
m=122;
memset(cnt,0,sizeof(cnt));
for(int i=1;i<=n;i++) ++cnt[rk[i]=s[i]];
for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
for(int i=n;i;i--) sa[cnt[rk[i]]--]=i;
// rk[n+1]=0;
for(int k=1;k<=n;k<<=1)
{
int num=0;
for(int i=n-k+1;i<=n;i++) pos[++num]=i;
for(int i=1;i<=n;i++) if(sa[i]>k) pos[++num]=sa[i]-k;
memset(cnt,0,sizeof(cnt));
for(int i=1;i<=n;i++) ++cnt[rk[i]];
for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
for(int i=n;i;i--) sa[cnt[rk[pos[i]]]--]=pos[i];
num=0;
memcpy(oldrk,rk,sizeof(rk));
for(int i=1;i<=n;i++) rk[sa[i]]=cmp(sa[i],sa[i-1],k)?num:++num;
if(num==n) break;
m=num;
}
for(int i=1;i<=n;i++) rk[sa[i]]=i;
int k=0;
for(int i=1;i<=n;i++)
{
if(k) --k;
while(s[i+k]==s[sa[rk[i]-1]+k]) ++k;
ht[rk[i]]=k;
}
}
int lens,lent;
int judge(int x)
{
int minn=sa[1],maxn=sa[1];
for(int i=2;i<=n;i++)
{
if(ht[i]>=x)
{
minn=min(minn,sa[i]);
maxn=max(maxn,sa[i]);
}
else minn=maxn=sa[i];
if(minn+x-1<=lens&&maxn>lens+1) return 1;
}
return 0;
}
int main()
{
scanf("%s%s",s+1,t+1);
lens=strlen(s+1),lent=strlen(t+1);
n=lens;
s[++n]=0;
for(int i=1;i<=lent;i++) s[++n]=t[i];
getsa();
int l=1,r=min(lens,lent),ans=0;
while(l<=r)
{
int mid=(l+r)/2;
if(judge(mid))
{
ans=mid;
l=mid+1;
}
else r=mid-1;
}
printf("%d
",ans);
// stop;
return 0;
}