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号
浙公网安备 33010602011771号