[后缀数组]JZOJ 3337 wyl889的TLE
分析
发现可以枚举端点i,然后修改字符前的长度是len=LCP(B[i..m],A)
则ans=max(len+1+LCP(B[i+len+1..m],A[len+2..n]))
考场看到LCP时 心 肺 停 止
背完SA板子以后随便搞搞就欧克了
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int N=1e6+10; int n,n1,n2,m; int c[N],x[N],y[N],sa[N],rk[N],height[(1<<21)+1][21],pow[21],ans; char s[N],s2[N]; int MIN(int l,int r) { if (l>r) swap(l,r); l++; int ans=2147483647; for (int k=20;k>=0;k--) if (l+pow[k]-1<=r) { ans=min(ans,height[l][k]); l+=pow[k]; } return ans; } void Solve() { int len,l; for (int i=1;i<=n2;i++) { len=min(min(n1,n2-i+1),MIN(rk[i],rk[n2+1])); ans=max(ans,min(min(n1,n2-i+1),len+1)); ans=max(ans,min(min(n1,n2-i+1),len)); l=min(min(n1,n2-i+1)-len-1,MIN(rk[i+len+1],rk[n2+len+2])); ans=max(ans,len+1+l); } } void SA() { memset(c,0,sizeof c); for (int i=1;i<=n;i++) c[x[i]=s2[i]]++; for (int i=1;i<=m;i++) c[i]+=c[i-1]; for (int i=n;i;i--) sa[c[x[i]]--]=i; for (int k=1;k<=n;k<<=1) { memset(c,0,sizeof c);int cnt=0; for (int i=n-k+1;i<=n;i++) y[++cnt]=i; for (int i=1;i<=n;i++) if (sa[i]>k) y[++cnt]=sa[i]-k; for (int i=1;i<=n;i++) c[x[i]]++; for (int i=1;i<=m;i++) c[i]+=c[i-1]; for (int i=n;i;i--) sa[c[x[y[i]]]--]=y[i],y[i]=0; swap(x,y);cnt=0; x[sa[1]]=++cnt; for (int i=2;i<=n;i++) x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?cnt:++cnt; if (cnt==n) break; m=cnt; } } void Get_Height() { for (int i=1;i<=n;i++) rk[sa[i]]=i; int k=0; for (int i=1;i<=n;i++) { if (rk[i]==1) continue; k=max(0,k-1); int j=sa[rk[i]-1]; while (s2[j+k]==s2[i+k]&&i+k<=n&&j+k<=n) k++; height[rk[i]][0]=k; } } void RMQ() { for (int k=1;k<=20;k++) for (int i=1;i<=n;i++) height[i][k]=min(height[i][k-1],height[i+pow[k-1]][k-1]); } int main() { scanf("%s",s+1);scanf("%s",s2+1); n1=strlen(s+1);n=strlen(s2+1);m='z';n2=n; for (int i=n+1;i<=n1+n;i++) s2[i]=s[i-n]; n+=n1; pow[0]=1; for (int i=1;i<=20;i++) pow[i]=pow[i-1]<<1; SA();memset(height,0x7f,sizeof height); Get_Height(); RMQ(); Solve(); printf("%d",ans); }
在日渐沉没的世界里,我发现了你。