BZOJ2534 Uva10829L-gap字符串 字符串 SA ST表
原文链接https://www.cnblogs.com/zhouzhendong/p/9240665.html
题目传送门 - BZOJ2534
题意
有一种形如 $uvu$ 形式的字符串,其中 $u$ 是非空字符串,且 $V$ 的长度正好为 $L$ ,那么称这个字符串为 $L-Gap$ 字符串。
给出一个字符串 $S$ ,以及一个正整数 $L$ ,问 $S$ 中有多少个 $L-Gap$ 子串。
$L< |S|\leq 5\times 10^4$
题解
我甚至怀疑写这题题解是否必要……
这题和BZOJ2119简直一毛一样啊。
BZOJ2119 股市的预测 字符串 SA ST表
代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int N=100005; int n,m,tot=0,a[N]; char s[N]; map <int,int> mp; int SA[N],rank[N],tmp[N],height[N],tax[N]; int ST[N][20]; void Sort(int n,int m){ for (int i=0;i<=m;i++) tax[i]=0; for (int i=1;i<=n;i++) tax[rank[i]]++; for (int i=1;i<=m;i++) tax[i]+=tax[i-1]; for (int i=n;i>=1;i--) SA[tax[rank[tmp[i]]]--]=tmp[i]; } bool cmp(int rk[],int x,int y,int w){ return rk[x]==rk[y]&&rk[x+w]==rk[y+w]; } void Suffix_Array(int s[],int n){ memset(SA,0,sizeof SA); memset(tmp,0,sizeof tmp); memset(rank,0,sizeof rank); memset(height,0,sizeof height); for (int i=1;i<=n;i++) rank[i]=s[i],tmp[i]=i; int m=234; Sort(n,m); for (int w=1,p=0;p<n;w<<=1,m=p){ p=0; for (int i=n-w+1;i<=n;i++) tmp[++p]=i; for (int i=1;i<=n;i++) if (SA[i]>w) tmp[++p]=SA[i]-w; Sort(n,m); swap(rank,tmp); rank[SA[1]]=p=1; for (int i=2;i<=n;i++) rank[SA[i]]=cmp(tmp,SA[i],SA[i-1],w)?p:++p; } for (int i=1,j,k=0;i<=n;height[rank[i++]]=k) for (k=max(k-1,0),j=SA[rank[i]-1];s[i+k]==s[j+k];k++); height[1]=0; } void Get_ST(int n){ memset(ST,0,sizeof ST); for (int i=1;i<=n;i++){ ST[i][0]=height[i]; for (int j=1;j<20;j++){ ST[i][j]=ST[i][j-1]; if (i-(1<<(j-1))>0) ST[i][j]=min(ST[i][j],ST[i-(1<<(j-1))][j-1]); } } } int Query(int L,int R){ int val=floor(log(R-L+1)/log(2)); return min(ST[L+(1<<val)-1][val],ST[R][val]); } int LCP(int x,int y){ x=rank[x],y=rank[y]; return Query(min(x,y)+1,max(x,y)); } int LCS(int x,int y){ return LCP(n*2+2-x,n*2+2-y); } int main(){ scanf("%d",&m); scanf("%s",s+1); n=strlen(s+1); for (int i=1;i<=n;i++) a[i]=a[n*2+2-i]=s[i]; a[n+1]=233; Suffix_Array(a,n*2+1); Get_ST(n*2+1); LL ans=0; for (int L=1;L<=n;L++) for (int i=1;i+L+m<=n;i+=L){ int x=i,y=i+L+m; int lcp=min(LCP(x,y),L),lcs=min(LCS(x,y),L); int len=lcp+lcs-(lcp>0&&lcs>0); ans+=max(len-L+1,0); } printf("%lld\n",ans); return 0; }