Problem J
L-Gap Substrings
Input:StandardInput
Output: Standard Output
If a string is in the form UVU, where Uis not empty, and V has exactly L characters, we say UVUis an L-Gap string. For example, abcbabc is a 1-Gapstring. xyxyxyxyxy is both a 2-Gap string and also a 6-Gapstring, but not a 10-Gap string (because U is non-empty).
Given a string s, and a positiveinteger g, you are to find the number of g-Gap substrings in s.s contains lower-case letters only, and has at most 50,000characters.
Input
Thefirst line contains a single integer t(1<=t<=10), the number oftest cases. Each of the t followings contains an integer g(1<=g<=10)followed bya string s.
Output
For each test case, print thecase number and the number of g-Gapsubstrings. Look at the output for sample input for details.
Sample Input Output for Sample Input
2 1 bbaabaaaaa 5 abxxxxxab | Case 1: 7 Case 2: 1
|
给出L和一个串,输出格式为UVU的有多少个,V的长度为L。
做法和POJ3693类似。枚举U的长度i和UVU这个串的起始位置j,起始位置不是一个一个枚举,而是0,i,2*i...这样枚举。RMQ求出j和j+i+L位置的LCP,从j-L+1...j这一段处理方法是倒着求j-1和j+i+L-1的LCP(先把整个串在后面倒着复制一遍就是正着求对应位置的)。设sum=min(RMQ(sa.rank[j],sa.rank[j+i+L]),i)+min(RMQ(sa.rank[sa.n-j-1],sa.rank[sa.n-j-i-L-1]),i-1),那么以j-L+1...j起始的U长度为i的符合条件的串共有max(0,sum-i+1)个,自己画画就知道了。这样的时间复杂度(n+n/2+n/3...+1),为nlnn.
#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef pair<LL,LL> pii;
const int MAXN=50010*2;
const int MAXNODE=4*MAXN;
const int LOGMAXN=50;
int T,L,d[MAXN][LOGMAXN];
char str[MAXN];
struct SuffixArray{
int s[MAXN];
int c[MAXN];
int sa[MAXN];
int height[MAXN];
int rank[MAXN];
int t[MAXN],t2[MAXN];
int n;
void clear(){
n=0;
memset(sa,0,sizeof(sa));
}
void build_sa(int m){
int i,*x=t,*y=t2;
for(i=0;i<m;i++) c[i]=0;
for(i=0;i<n;i++) c[x[i]=s[i]]++;
for(i=1;i<m;i++) c[i]+=c[i-1];
for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
for(int k=1;k<n;k<<=1){
int p=0;
for(i=n-k;i<n;i++) y[p++]=i;
for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
for(i=0;i<m;i++) c[i]=0;
for(i=0;i<n;i++) c[x[y[i]]]++;
for(i=1;i<m;i++) c[i]+=c[i-1];
for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
swap(x,y);
p=1;
x[sa[0]]=0;
for(i=1;i<n;i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
if(p>=n) break;
m=p;
}
}
void build_height(){
int k=0;
for(int i=0;i<n;i++) rank[sa[i]]=i;
height[0]=0;
for(int i=0;i<n-1;i++){
if(k) k--;
int j=sa[rank[i]-1];
while(s[i+k]==s[j+k]) k++;
height[rank[i]]=k;
}
}
}sa;
void RMQ_init(){
for(int i=0;i<sa.n;i++) d[i][0]=sa.height[i];
for(int j=1;(1<<j)<=sa.n;j++)
for(int i=0;i+(1<<j)<=sa.n;i++) d[i][j]=min(d[i][j-1],d[i+(1<<(j-1))][j-1]);
}
int RMQ(int L,int R){
if(L>=R) swap(L,R);
L++;
int k=0;
while((1<<(k+1))<=R-L+1) k++;
return min(d[L][k],d[R-(1<<k)+1][k]);
}
void solve(int len){
int ans=0;
for(int i=1;i<=len/2;i++)
for(int j=0;j<len;j+=i){
int sum=0;
if(j+i+L<len) sum=min(RMQ(sa.rank[j],sa.rank[j+i+L]),i);
if(sa.n-j-i-L-1>=0) sum+=min(RMQ(sa.rank[sa.n-j-1],sa.rank[sa.n-j-i-L-1]),i-1);
ans+=max(0,sum-i+1);
}
printf("%d\n",ans);
}
int main(){
freopen("in.txt","r",stdin);
int cas=0;
scanf("%d",&T);
while(T--){
scanf("%d%s",&L,str);
sa.clear();
int len=strlen(str);
for(int i=0;i<len;i++) sa.s[sa.n++]=str[i]-'a'+1;
sa.s[sa.n++]=27;
for(int i=len-1;i>=0;i--) sa.s[sa.n++]=str[i]-'a'+1;
sa.s[sa.n++]=0;
sa.build_sa(30);
sa.build_height();
RMQ_init();
//for(int i=0;i<sa.n;i++) printf("i=%d %d\n",i,sa.height[i]);
printf("Case %d: ",++cas);
solve(len);
}
return 0;
}