mdzz
题解很简单:
钦定一对(i,j)可以不相等,贡献就是lcp(i+1,j+1)+lcs(i-1,j-1)
套路地
按照hei对lcp也就是height进行合并
最大化lcs
set启发式合并
错误点:
1.sa写错
2.a=fin(a),并查集也能写错
3.ST表(i+(1<<j)-1)<=n
**
#include<bits/stdc++.h> #define reg register int #define il inline #define fi first #define se second #define mk(a,b) make_pair(a,b) #define numb (ch^'0') #define pb push_back #define solid const auto & #define enter cout<<endl #define pii pair<int,int> using namespace std; typedef long long ll; template <class T>il void rd(T &x){ char ch;x=0;bool fl=false; while(!isdigit(ch=getchar())) (ch=='-')&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb); (fl==true)&&(x=-x); } template <class T>il void prt(T a[],int st,int nd){ for(reg i=st;i<=nd;++i) cout<<a[i]<<" ";cout<<endl; } namespace Miracle{ const int N=2e5+40000; char A[N],B[N]; int n,m; int lg[N]; struct SASA{ char s[N]; int id[N]; int xx[N],yy[N]; int buc[N],sa[N],rk[N]; int hei[N]; int f[N][20]; int n; void build(){ int m=130; int *x=xx,*y=yy; for(reg i=1;i<=n;++i) ++buc[x[i]=s[i]]; for(reg i=1;i<=m;++i) buc[i]+=buc[i-1]; for(reg i=1;i<=n;++i) sa[buc[x[i]]--]=i; for(reg k=1;k<=n;k<<=1){ int num=0; for(reg i=n-k+1;i<=n;++i) y[++num]=i; for(reg i=1;i<=n;++i){ if(sa[i]>k) y[++num]=sa[i]-k; } for(reg i=1;i<=m;++i) buc[i]=0; for(reg i=1;i<=n;++i) ++buc[x[i]]; for(reg i=1;i<=m;++i) buc[i]+=buc[i-1]; for(reg i=n;i>=1;--i) sa[buc[x[y[i]]]--]=y[i],y[i]=0; swap(x,y); num=1; x[sa[1]]=1; for(reg i=2;i<=n;++i){ x[sa[i]]=(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k])?num:++num; } if(num==n) break; m=num; } for(reg i=1;i<=n;++i) rk[sa[i]]=i; for(reg k=0,i=1;i<=n;++i){ if(k)--k; if(rk[i]==1) continue; int j=sa[rk[i]-1]; while(j+k<=n&&i+k<=n&&s[i+k]==s[j+k]) ++k; hei[rk[i]]=k; } for(reg i=1;i<=n;++i) f[i][0]=hei[i]; for(reg j=1;j<=17;++j){ for(reg i=1;(i+(1<<j)-1)<=n;++i){ f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]); } } //cout<<"string ";cout<<s+1<<endl; //cout<<" sa ";prt(sa,1,n); //cout<<" rk ";prt(rk,1,n); //cout<<" hei ";prt(hei,1,n); } int lcp(int x,int y){ //cout<<" calc lcp "<<x<<" "<<y<<endl; if(x==y) return n-x+1; x=rk[x],y=rk[y]; if(x>y) swap(x,y); ++x; int len=lg[y-x+1]; int ret=min(f[x][len],f[y-(1<<len)+1][len]); //cout<<" retlcp "<<ret<<endl; return ret; } }str[2]; int rev(int x){ return x>n?n+(n+m)-x+1:n-x+1; } struct po{ int x; po(){} po(int xx){ x=xx; } bool friend operator <(po a,po b){ int ta=rev(a.x); int tb=rev(b.x); return str[1].rk[ta]<str[1].rk[tb]; } }; int fa[N]; int id[N]; bool cmp(int x,int y){ return str[0].hei[x]>str[0].hei[y]; } set<po>s[N][2]; int ans; int fin(int x){ return fa[x]==x?x:fa[x]=fin(fa[x]); } void merge(int a,int b,int l){ //cout<<" merge ----------"<<a<<" "<<b<<" "<<l<<endl; //cout<<" sz a "<<s[a][0].size()<<" "<<s[a][1].size()<<endl; //cout<<" sz b "<<s[b][0].size()<<" "<<s[b][1].size()<<endl; a=fin(a),b=fin(b); fa[b]=a; if(s[a][0].size()+s[a][1].size()<s[b][0].size()+s[b][1].size()) s[a][0].swap(s[b][0]),s[a][1].swap(s[b][1]); if(s[a][1].size()){ for(solid y:s[b][0]){ auto bc=s[a][1].upper_bound(y); if(bc!=s[a][1].end()){ ans=max(ans,1+l+str[1].lcp(rev(y.x),rev((*bc).x))); } if(bc!=s[a][1].begin()){ --bc; ans=max(ans,1+l+str[1].lcp(rev(y.x),rev((*bc).x))); } } } if(s[a][0].size()){ for(solid y:s[b][1]){ //cout<<" twotowto "<<y.x<<endl; auto bc=s[a][0].upper_bound(y); if(bc!=s[a][0].end()){ // cout<<" bac "<<(*bc).x<<endl; ans=max(ans,1+l+str[1].lcp(rev(y.x),rev((*bc).x))); } if(bc!=s[a][0].begin()){ --bc; // cout<<" pre "<<(*bc).x<<endl; ans=max(ans,1+l+str[1].lcp(rev(y.x),rev((*bc).x))); } } } for(solid y:s[b][0]) s[a][0].insert(y); for(solid y:s[b][1]) s[a][1].insert(y); //cout<<" after ans "<<ans<<endl; } int main(){ scanf("%s",A+1);n=strlen(A+1); scanf("%s",B+1);m=strlen(B+1); lg[0]=0; for(reg i=1;i<=n+m+3;++i){ lg[i]=(i>>(lg[i-1]+1))?lg[i-1]+1:lg[i-1]; } for(reg i=2;i<=n;++i){ str[0].s[++str[0].n]=A[i]; //id[str[0].n]=1; } str[0].s[++str[0].n]='A'; for(reg i=2;i<=m;++i){ str[0].s[++str[0].n]=B[i]; //id[str[0].n]=2; } str[0].s[++str[0].n]='B'; reverse(A+1,A+n+1); reverse(B+1,B+m+1); for(reg i=2;i<=n;++i){ str[1].s[++str[1].n]=A[i]; //id[str[1].n]=1; } str[1].s[++str[1].n]='A'; for(reg i=2;i<=m;++i){ str[1].s[++str[1].n]=B[i]; //id[str[1].n]=2; } str[1].s[++str[1].n]='B'; str[0].build(); str[1].build(); for(reg i=1;i<=str[0].n;++i){ fa[i]=i; id[i]=i; if(i<=n){ s[i][0].insert(po(i)); }else{ s[i][1].insert(po(i)); } } sort(id+1,id+str[0].n+1,cmp); for(reg i=1;i<=str[0].n;++i){ int x=id[i]; if(x==1) continue; merge(str[0].sa[x],str[0].sa[x-1],str[0].hei[x]); } printf("%d",ans); return 0; } } signed main(){ Miracle::main(); return 0; }