经典题
注意匹配的时候:用t串去s串的SAM里进行匹配,和字典树一样遍历t中字符,用cur记录当前已经匹配的长度,如果能当前字符能匹配则cur++(这里不能直接用cur=len[now]),反之用link指针进行失配,直到完成匹配后cur=len[now]
为什么匹配成功时不能直接cur=len[now]?因为自动机上的转移是在后面加一个字符,但是不保证前面不加字符,因为每个结点的len是该节点代表的maxlen
但是失配后再转移成功则可以用cur=len[now],因为失配结点代表的最短串长度都有len[now]+1,即到了这个状态,那么t串一定有minlen[now]的长度,所以其link指向的状态的maxlen[now]=minlen[now-1]一定是满足条件的!
#include<bits/stdc++.h>
using namespace std;
#define maxn 250005
struct SAM{
int cnt,last;
int nxt[maxn<<1][26];
int link[maxn<<1];
int len[maxn<<1];
SAM(){
cnt=last=1;
}
void insert(int c){
int p=last,np=last=++cnt;
len[np]=len[p]+1;
for(;p&&!nxt[p][c];p=link[p])
nxt[p][c]=np;
if(!p){link[np]=1;return;}
int q=nxt[p][c];
if(len[q]==len[p]+1){link[np]=q;return;}
int clone=++cnt;
link[clone]=link[q];
len[clone]=len[p]+1;
memcpy(nxt[clone],nxt[q],sizeof nxt[q]);
link[q]=link[np]=clone;
for(;p&&nxt[p][c]==q;p=link[p])
nxt[p][c]=clone;
}
int query(char *s){
int now=1,Len=strlen(s),cur=0,Max=0;
for(int i=0;i<Len;i++){
int c=s[i]-'a';
if(nxt[now][c]){
now=nxt[now][c];
cur++;
}
else {
while(now && !nxt[now][c])now=link[now];
if(now){
cur=len[now]+1;
now=nxt[now][c];
}
else {
now=1;
cur=0;
}
}
Max=max(Max,cur);
}
return Max;
}
}p;
char s[maxn],t[maxn];
int main(){
scanf("%s%s",s,t);
int len1=strlen(s);
int len2=strlen(t);
for(int i=0;i<len1;i++)
p.insert(s[i]-'a');
cout<<p.query(t)<<endl;
}