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