Uva 10829 : L-Gap Substrings
题目链接:https://vjudge.net/problem/UVA-10829
题目大意:给出一个长度为\(n\)的字符串和\(m\),求有多少个子串满足ABA的形式,且\(|B|\geq m\),\(n\leq 50000\)
解析:
我们可以枚举A的长度,然后通过设关键点将整个字符串每\(|A|\)个字符划为一段,则对于任意一个子串,若它满足ABA的形式,则它的第一个"A"段一定覆盖某段的第一个字符。
那么我们可以对于每一段的第一个字符\(S_j\),求出它与\(S_{j+i+m}\)的向前和向后的LCP,然后随缘统计一下(雾),注意当前A段不能覆盖别的段的首字符。
代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#define rep(i,x,y) for (int i=x;i<=y;i++)
#define dep(i,y,x) for (int i=y;i>=x;i--)
#define sz(x) (int)(x.size())
using namespace std;
typedef long long LL;
const int maxn=100000+23,maxlogn=15+1;
int T,n,m,maxi,k,j,h,L,R,len;
int lcp[maxn],sa[maxn],temp[maxn],c[maxn],rnk[maxn],nxt[maxn],num[maxn],lp[maxn],rp[maxn],ls[maxn],rs[maxn];
int ds[maxn][maxlogn],dp[maxn][maxlogn];
LL ans;
char s[maxn];
void Suffix_Array()
{
maxi=n;
rep(i,1,n) sa[i]=i,rnk[i]=(int)(s[i]),maxi=max(maxi,rnk[i]);
for (int len=1;len<=n;len<<=1)
{
memset(c,0,sizeof(c));
rep(i,1,n)
{
k=sa[i];
if ((k+len)>n) nxt[k]=0; else nxt[k]=rnk[k+len];
c[nxt[k]]++;
}
rep(i,1,maxi) c[i]+=c[i-1];
dep(i,n,1) temp[c[nxt[sa[i]]]--]=sa[i];
memset(c,0,sizeof(c));
rep(i,1,n) c[rnk[temp[i]]]++;
rep(i,1,maxi) c[i]+=c[i-1];
dep(i,n,1) sa[c[rnk[temp[i]]]--]=temp[i];
temp[sa[1]]=1;
rep(i,2,n)
{
temp[sa[i]]=temp[sa[i-1]];
if ((rnk[sa[i]]!=rnk[sa[i-1]])||(nxt[sa[i]]!=nxt[sa[i-1]])) temp[sa[i]]++;
}
rep(i,1,n) rnk[i]=temp[i];
}
}
void LCP_Array()
{
rep(i,1,n) rnk[sa[i]]=i;
h=0;
rep(i,1,n)
{
j=sa[rnk[i]-1];
if (h>0) h--;
for (;((i+h)<=n)&&((j+h)<=n);h++)
if (s[i+h]!=s[j+h]) break;
lcp[rnk[j]]=h;
}
}
void RMQ_init()
{
k=0;
rep(i,1,n)
{
if ((1<<(k+1))<i) k++;
num[i]=k;
}
rep(i,1,n) dp[i][0]=lp[i],ds[i][0]=ls[i];
rep(k,1,maxlogn-1)
rep(i,1,n)
{
dp[i][k]=min(dp[i][k-1],dp[i+(1<<(k-1))][k-1]);
ds[i][k]=min(ds[i][k-1],ds[i+(1<<(k-1))][k-1]);
}
}
int query(int d[maxn][maxlogn],int l,int r)
{
if (l>r) swap(l,r);
r--;
int len=num[r-l+1];
return min(d[l][len],d[r-(1<<len)+1][len]);
}
int main()
{
scanf("%d",&T);
rep(ca,1,T)
{
scanf("%d",&m);
scanf("%s",s+1);
n=strlen(s+1);
Suffix_Array();
LCP_Array();
rep(i,1,n) ls[i]=lcp[i],rs[i]=rnk[i];
reverse(s+1,s+n+1);
Suffix_Array();
LCP_Array();
rep(i,1,n) lp[i]=lcp[i],rp[n-i+1]=rnk[i];
RMQ_init();
ans=0;
for (int i=1;((i<<1)+m)<=n;i++)
{
len=(i<<1)+m;
for (int j=1;j<=n;j+=i)
{
R=min(j+i-1,j+query(ds,rs[j],rs[j+i+m])-1);
L=max(j-i+1,j-query(dp,rp[j],rp[j+i+m])+1);
if ((R-L-i+2)>0) ans+=(LL)(R-L-i+2);
}
}
printf("Case %d: %lld\n",ca,ans);
}
return 0;
}

浙公网安备 33010602011771号