码迷,mamicode.com
首页 > 其他好文 > 详细

[2018 ACM-ICPC 焦作赛区网络赛] H - String and Times(后缀自动机)

时间:2018-09-16 15:59:07      阅读:366      评论:0      收藏:0      [点我收藏+]

标签:出现   struct   main   uppercase   turn   getheight   inpu   c++   \n   

Now you have a string consists of uppercase letters, two integers AA and BB. We call a substring wonderful substring when the times it appears in that string is between AA and BB (A \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 SS, two integers AA and BB.

\sum length(S) \le 2 \times 10^6∑length(S)≤2×106,

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
题意:给你任意一个由大写字母构成的字符串,统计其出现n到m次的字串个数
思路:这道题和HDU 6194很像,那道题是要统计恰好出现k次的字串个数,是用后缀自动机做的,那么这道题其实可以直接把最后询问的操作改成GetK(k,n)-GetK(k+m+1,n))即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MaxN=2e5+100;
const ll MAXN = MaxN;
ll cntA[MaxN],cntB[MaxN],tsa[MAXN],A[MAXN],B[MAXN];
ll sa[MAXN],Rank[MAXN],h[MAXN];
char ch[MAXN];
struct Node{
    ll val,index;
    Node(ll val_,ll index_):val(val_),index(index_){
    }
    bool operator < (const Node b)const{
        if (val==b.val){
            return b.index<index;
        }
        return b.val<val;
    }
};
priority_queue<Node>pq;
void GetSa(char *ch,ll *sa,ll *rank,ll n){
 
    for(ll i=0;i<MaxN;i++)  cntA[i]=0;
    for(ll i=1;i<=n;i++)   cntA[ch[i]]++;
    for(ll i=1;i<=MaxN;i++) cntA[i]+=cntA[i-1];
    for(ll i=n;i;i--)  sa[cntA[ch[i]]--]=i;
    rank[sa[1]]=1;
    for(ll i=2;i<=n;i++){
        rank[sa[i]]=rank[sa[i-1]];
        if(ch[sa[i]]!=ch[sa[i-1]])  rank[sa[i]]++;
    }
    for(ll l=1;rank[sa[n]]<n;l<<=1){
        for(ll i=0;i<MaxN;i++)  cntA[i]=0;
        for(ll i=0;i<MaxN;i++)  cntB[i]=0;
        for(ll i=1;i<=n;i++){
            cntA[A[i]=rank[i]]++;
            cntB[B[i]=(i+l<=n)?rank[i+l]:0]++;
        }
        for(ll i=1;i<MaxN;i++)   cntB[i]+=cntB[i-1];
        for(ll i=n;i;i--)  tsa[cntB[B[i]]--]=i;
        for(ll i=1;i<MaxN;i++)  cntA[i]+=cntA[i-1];
        for(ll i=n;i;i--)  sa[cntA[A[tsa[i]]]--]=tsa[i];
        rank[sa[1]]=1;
        for(ll i=2;i<=n;i++){
            rank[sa[i]]=rank[sa[i-1]];
            if(A[sa[i]]!=A[sa[i-1]] || B[sa[i]]!=B[sa[i-1]])    rank[sa[i]]++;
        }
    }
}
 
void GetHeight(char *ch,ll *sa,ll *rank,ll *height,ll n){
 
    GetSa(ch,sa,rank,n);
    for(ll i=1,j=0;i<=n;i++){
        if(j)   j--;
        while(ch[i+j]==ch[sa[rank[i]-1]+j]) j++;
        height[rank[i]]=j;
    }
}
ll GetK(ll k,ll n){
    ll ans=0;
    k--;
    if(k==0){
        for(ll i=1;i<=n;++i)   ans=ans+(n-sa[i]+1-h[i]);
        return ans;
    }
    while (!pq.empty())pq.pop();
    for (ll i=2;i<=n;i++){
        while (!pq.empty()&&pq.top().index<i-k+1)pq.pop();
        pq.push(Node(h[i],i));
        if (i>k){
            ll top = pq.top().val;
            ll last = h[i-k];
            ans +=max((ll)0,top-last);
        }
    }
    return ans;
}
 
void Run(){
    ll n,k,m;
    while(~scanf("%s %lld %lld",ch+1,&k,&m)){
        n=strlen(ch+1);
        GetHeight(ch,sa,Rank,h,n);
        printf("%lld\n",GetK(k,n)-GetK(k+m+1,n));  //至少出现n次的字串数-至少出现m+1次的字串数
    }
}
int main(){
    Run();
    return 0;
}

 

[2018 ACM-ICPC 焦作赛区网络赛] H - String and Times(后缀自动机)

标签:出现   struct   main   uppercase   turn   getheight   inpu   c++   \n   

原文地址:https://www.cnblogs.com/jiaqi666/p/9655165.html

踩
(0)
赞
(0)
   
举报
评论 一句话评论(0)
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!