版权声明:小白一个,欢迎各位指错。 https://blog.csdn.net/qq_36424540/article/details/82729342
Now you have a string consists of uppercase letters, two integers AAA and BBB. We call a substring wonderful substring when the times it appears in that string is between AAA and BBB (A≤times≤BA \le times \le BA≤times≤B). Can you calculate the number of wonderful substrings in that string?
Input
Input has multiple test cases.
For each line, there is a string SSS, two integers AAA and BBB.
∑length(S)≤2×106\sum length(S) \le 2 \times 10^6∑length(S)≤2×106,
1≤A≤B≤length(S)1 \le A \le B \le length(S)1≤A≤B≤length(S)
Output
For each test case, print the number of the wonderful substrings in a line.
样例输入
AAA 2 3
ABAB 2 2
样例输出
2
3
注意空间,不要WA的很惨
询问在区间 [a,b] 中的,我们考虑 >=a的数量, 因为他是比较好求的, 然后考虑>b 的数量, 然后减一下就好了。
注意长度为1的时候,我们需要特判,因为我写的是,不能判断的,我们判断得算后面一个和前面的
扫描二维码关注公众号,回复:
3273918 查看本文章
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define rep(i,a,b) for(int i=a;i<b;++i)
#define per(i,a,b) for(int i=b-1;i>=a;--i)
const int N=5e5+10;
//后缀数组模板
int r[N];//需先将字符串 转换成 int 类型;末尾添加最小字符.
int sa[N],t[N],t2[N],c[N];
void build_sa(int n,int m) //n的长度+1,因为最后加了一个最小的字符。 m的长度+1,因为m取不到。
{
int *x=t,*y=t2;
rep(i,0,m)c[i]=0;
rep(i,0,n)c[x[i]=r[i]]++;
rep(i,1,m)c[i]+=c[i-1];
per(i,0,n)sa[--c[x[i]]]=i;
for(int k=1; k<=n; k<<=1) {
int p=0;
rep(i,n-k,n)y[p++]=i;
rep(i,0,n)if(sa[i]>=k)y[p++]=sa[i]-k;
rep(i,0,m)c[i]=0;
rep(i,0,n)c[x[y[i]]]++;
rep(i,0,m)c[i]+=c[i-1];
per(i,0,n)sa[--c[x[y[i]]]]=y[i];
swap(x,y);
p=1;
x[sa[0]]=0;
rep(i,1,n)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;
}
}
int rk[N],height[N];//注意heigh的含义,所以注意范围是不是要+1
void getHeight(int n) //n的长度也要加1
{
int k=0; //跳过最小的 后面的添加字符
rep(i,0,n)rk[sa[i]]=i;
rep(i,0,n-1) { //最后的那个添加的不要计算,否则RE
if(k)k--;
int j=sa[rk[i]-1];//注意不要有rk[i]=0,所以我们通常在末尾添加一个 最小值,让他把0拿走
while(r[i+k]==r[j+k])k++;
height[rk[i]]=k;
}
}
int dp[N][20];
void get_rmq(int n)
{
rep(i,1,n)dp[i][0]=height[i];
for(int j=1; (1<<j)<=n; ++j) {
for(int i=1; i+(1<<j)-1<=n; ++i) {
dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
}
}
int Log[N];
int RMQ(int l,int r)
{
int n=r-l+1,t=Log[n];
int ans1=dp[l][t],ans2=dp[r-(1<<t)+1][t];
return min(ans1,ans2);
}
//end
char s[N];
int main()
{
Log[1]=0;
rep(i,2,N)Log[i]=Log[i/2]+1;
//rep(i,1,10)printf("i:%d %d\n",i,Log[i]);
int a,b;
while(scanf("%s %d %d",s,&a,&b)==3) {
int len=strlen(s);
rep(i,0,len)r[i]=s[i]-'A'+1;
r[len]=0;
//printf("%s a:%d b:%d\n",s,a,b);
build_sa(len+1,26+1);
getHeight(len+1);
//printf("11111\n");
get_rmq(len+1);
//rep(i,1,len+1)printf("i:%d h:%d\n",i,height[i]);
LL sum1=0,sum2=0;
if(a==1) {
for(int i=1;i<=len;i++)sum1=sum1+len-sa[i]-height[i];
//sum1=len;//SB
} else {
for(int i=1; i<=len-a+1; i++) {
LL t=RMQ(i+1,i+a-1);
//if(t<=height[i])continue;
sum1+=t;
sum1-=min(t,1LL*height[i]);
//printf("t:%lld heig:%d\n",t,height[i]);
}
}
b++;
for(int i=1; i<=len-b+1; i++) {
LL t=RMQ(i+1,i+b-1);
sum2+=t;
sum2-=min(t,1LL*height[i]);//考虑当前的串的结尾,和上一个结尾的关系
}
//printf("sum1:%lld sum2:%lld\n",sum1,sum2);
printf("%lld\n",sum1-sum2);
}
return 0;
}