给定一个字符串 A和1个字符串 B ,求 B 和 A 中的最长公共子串。(len(a、b)<=2e5)
只需要对一个串建一个 s a m sam sam
然后把另一个串在上面跑就是了
如果发现当前已匹配好的地方的下一个字符不一样,就沿着当前节点的 l i n k link link一直往上跳,跳到第一个能匹配的地方跳下去就可以了
因为 e n d p o s endpos endpos的性质这显然是对的
#include<bits/stdc++.h>
using namespace std;
inline int read(){
char ch=getchar();
int res=0;
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return res;
}
struct node{
int len,link,nxt[27];
bool cl;
};
#define max(a,b) (((a)>(b))?a:b)
const int N=200005;
node st[N<<1];
int tot,ans,last;
char a[N];
inline void init(){
tot=last=0;
st[0].len=0,st[0].link=-1;
++tot;
}
inline void sa_extend(int c){
int cur=tot++;
st[cur].len=st[last].len+1;
int p;
for(p=last;p!=-1&&!st[p].nxt[c];p=st[p].link) st[p].nxt[c]=cur;
if(p==-1)st[cur].link=0;
else{
int q=st[p].nxt[c];
if(st[p].len+1==st[q].len)st[cur].link=q;
else {
int clo=tot++;
st[clo]=st[q];
st[clo].len=st[p].len+1;
for(;p!=-1&&st[p].nxt[c]==q;p=st[p].link)st[p].nxt[c]=clo;
st[q].link=st[cur].link=clo;
}
}
last=cur;
}
int main(){
scanf("%s",a+1),init();
int len=strlen(a+1);
for(int i=1;i<=len;i++)sa_extend(a[i]-'a'+1);
scanf("%s",a+1),len=strlen(a+1);
int pos=0,tmp=0;
for(int i=1;i<=len;i++){
int nx=a[i]-'a'+1;
if(st[pos].nxt[nx])pos=st[pos].nxt[nx],tmp++;
else {
while(pos!=-1&&!st[pos].nxt[nx])pos=st[pos].link;
if(pos==-1)pos=0,tmp=0;
else tmp=st[pos].len+1,pos=st[pos].nxt[nx];
}
ans=max(ans,tmp);
}
cout<<ans;
}