String and Times

版权声明:小白一个,欢迎各位指错。 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的时候,我们需要特判,因为我写的是,不能判断的,我们判断得算后面一个和前面的

#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;
}

猜你喜欢

转载自blog.csdn.net/qq_36424540/article/details/82729342