题意:求两个字符串的LCS
这个题是SA的经典题,也是SAM的经典题
SA做法:连接两个字符串(中间加个#)让后求height,Answer=Max{height[i]}
SAM做法:从开头匹配字符串,如果当前节点x能继续匹配就继续
如果不能匹配,就令x=f[x]直到x为根或者可以继续匹配,这样显然是正确的,因为f[x]显然是x的后缀
#include<stdio.h> #include<string.h> #include<algorithm> #define N 200010 using namespace std; char str[N]; int s[N][26],mx[N],f[N],sz[N]; int n,m,cnt=1,lst=1,v[N],r[N],ans=0; inline int extend(char c){ int p=lst,np=lst=++cnt,q,nq; c-='a'; sz[np]=1; mx[np]=mx[p]+1; for(;p&&!s[p][c];p=f[p]) s[p][c]=np; if(!p) return f[np]=1; q=s[p][c]; if(mx[q]==mx[p]+1) f[np]=q; else{ nq=++cnt; mx[nq]=mx[p]+1; f[nq]=f[q]; f[q]=f[np]=nq; memcpy(s[nq],s[q],26<<2); for(;p&&s[p][c]==q;p=f[p]) s[p][c]=nq; } } int main(){ scanf("%s",str+1); n=strlen(str+1); for(int i=1;i<=n;++i) extend(str[i]); scanf("%s",str+1); n=strlen(str+1); for(int i=1,x=1,l=0;i<=n;++i){ if(s[x][str[i]-'a']) x=s[x][str[i]-'a'],++l; else{ while(x&&!s[x][str[i]-'a']) x=f[x]; if(!x) x=1,l=0; else l=mx[x]+1,x=s[x][str[i]-'a']; } ans=max(ans,l); } printf("%d\n",ans); }