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

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

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

时间: 2024-10-10 02:33:40

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

2014 ACM/ICPC 鞍山赛区网络赛(清华命题)

为迎接10月17号清华命题的鞍山现场赛 杭电上的题目 Biconnected(hdu4997)      Rotate(hdu4998)     Overt(hdu4999)   Clone(hdu5000)   Walk(hdu5001)   LianLianKan   Rescue   Spy's Work   Color the Tree   The Ghost Blows Light   USACO ORZ   2013/8/27

hdu 4438 第37届ACM/ICPC 天津赛区现场赛H题

题意:Alice和Bob两个人去打猎,有两种(只)猎物老虎和狼: 杀死老虎得分x,狼得分y: 如果两个人都选择同样的猎物,则Alice得分的概率是p,则Bob得分的概率是(1-p): 但是Alice事先知道Bob先选老虎的概率是Q,问Alice得分的期望最大值是 求期望 如果先去打老虎,则会有bob先去打狼和bob去打老虎两种情况,期望相加则是alice去打老虎的期望,然后求打狼的期望,比较大小即可 1 #include<cstdio> 2 #include<iostream> 3

ACM-ICPC 2018 焦作赛区网络预赛 H题 String and Times(SAM)

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

ACM-ICPC 2018 焦作赛区网络预赛 H、L

https://nanti.jisuanke.com/t/31721 题意 n个位置 有几个限制相邻的三个怎么怎么样,直接从3开始 矩阵快速幂进行递推就可以了 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const ll mod=1e9+7,maxn=9; 5 struct Matrix 6 { 7 ll m[maxn][maxn]; 8 Matrix() 9 { 10 memset(m

HDU 5875 Function -2016 ICPC 大连赛区网络赛

题目链接 网络赛的水实在太深,这场居然没出线zzz,差了一点点,看到这道题的的时候就剩半个小时了.上面是官方的题意题解,打完了才知道暴力就可以过,暴力我们当时是想出来了的,如果稍稍再优化一下估计就过了zzz.去年有一场现场赛也是n=1000,n^3过了,看来关键时刻实在做不出来就得大胆暴力啊. #include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e5+5; int a[maxn]

[2018 ACM-ICPC 焦作赛区网络赛] G - Give Candies(找规律+快速幂)

题目链接 There are N children in kindergarten. Miss Li bought them N candies. To make the process more interesting, Miss Li comes up with the rule: All the children line up according to their student number (1...N)(1...N), and each time a child is invite

2014 ACM/ICPC 牡丹江赛区现场赛

最近突然感觉状态不佳,可能是天冷的缘故? 赛后来做牡丹江赛区的题目 [A]3819 Average Score -- 签到题 [B] [C] [D] [E] [F] [G] [H] [I] [J] [K]3829 Known Notation -- 贪心 + 模拟 [A]3819 Average Score -- 签到题 Average Score Time Limit: 2 Seconds                                     Memory Limit: 65

2017 acm icpc 沈阳(网络赛)5/12 题解

比赛中较...能做的5道题 hdoj6195. cable cable cable 题目链接 : http://acm.hdu.edu.cn/showproblem.php?pid=6195 题目大意 : 略 规律 : 答案 = k+(m-k)*k hdoj6198. number number number 题目链接 : http://acm.hdu.edu.cn/showproblem.php?pid=6198 题目大意  : 给你一个整数n.问你n个斐波那契数(可重复)不能构成哪些数,输出

hdu 4431 第37届ACM/ICPC 天津赛区现场赛A题 枚举

题意:就是给了13张牌.问增加哪些牌可以胡牌.m是数字,s是条,p是筒,c是数字 胡牌有以下几种情况: 1.一个对子 +  4组 3个相同的牌或者顺子.  只有m.s.p是可以构成顺子的.东西南北这样的牌没有顺子. 2.7个不同的对子. 3.1m,9m,1p,9p,1s,9s,1c,2c,3c,4c,5c,6c,7c.  这13种牌每种都有,而且仅有这13种牌.肯定是有一种2张.其他的1张. 模拟即可,第一个对子的情况需要枚举 很麻烦的模拟,但是貌似稳银的很需要这题,所以这种难度必须要弄懂,加油