String and Times
2024-09-05 12:47:07
String and Times
时间限制: 1 Sec 内存限制: 128 MB
题目描述
Now you have a string consists of uppercase letters, two integers A and B. We call a substring wonderful substring when the times it appears in that string is between A and B (A ≤ times ≤ B). Can you calculate the number of wonderful substrings in that string?
输入
Input has multiple test cases.
For each line, there is a string S, two integers A and B.
∑Length(S)≤2×10^6,1≤A≤B≤length(S)
For each line, there is a string S, two integers A and B.
∑Length(S)≤2×10^6,1≤A≤B≤length(S)
输出
For each test case, print the number of the wonderful substrings in a line.
样例输入
AAA 2 3
ABAB 2 2
样例输出
2
3
题意:给定字符串,求出现次数在[l,r]内的不同字符串的个数。
思路:首先考虑求出现次数大于等于k次的字符串个数。后缀数组的height数组的定义为某个后缀串和它前一个后缀串(此处“前一个”意思是按照字典序的排名来的前一个)的最长公共前缀,那么height数组里若有连续的k-1个数的最小值为min,就代表有一个长度为min的字符串最少出现了k次。
#include<bits/stdc++.h>
#define INF LLONG_MAX/2
#define lson (rt*2)
#define rson (rt*2+1)
using namespace std;
const int N = 2e5+;
char s[N]; struct SuffixArray
{
int sa[N],rank[N],height[N],cnt[N],a1[N],a2[N],n,m,*x,*y;
void sort()
{
for(int i=; i<m; i++) cnt[i]=;
for(int i=; i<n; i++) cnt[x[i]]++;
for(int i=; i<m; i++) cnt[i]+=cnt[i-];
for(int i=n-; i>=; i--) sa[--cnt[x[y[i]]]]=y[i];
}
void build(char *s,int c_size)
{
n=strlen(s);
m=c_size;
x=a1;
y=a2;
for(int i=; i<n; i++) x[i]=s[i],y[i]=i;
x[n]=y[n]=-;
sort();
for(int k=; k<=n; k<<=)
{
int p=;
for(int i=n-k; i<n; i++) y[p++]=i;
for(int i=; i<n; i++) if(sa[i]>=k) y[p++]=sa[i]-k;
sort();
p=;
std::swap(x,y);
x[sa[]]=;
for(int i=; i<n; i++)
{
if(y[sa[i]]!=y[sa[i-]]||y[sa[i]+k]!=y[sa[i-]+k]) p++;
x[sa[i]]=p;
}
if(p+>=n) break;
m=p+;
}
for(int i=; i<n; i++) rank[sa[i]]=i;
height[]=;
int k=;
for(int i=; i<n; i++)
{
if(k) k--;
if(rank[i]==) continue;
int j=sa[rank[i]-];
while(i+k<n&&j+k<n&&s[i+k]==s[j+k]) k++;
height[rank[i]]=k;
}
}
} SA; struct node
{
long long val;
int l,r;
}tree[N<<];
void build(int rt,int l,int r)
{
int mid=(l+r)>>;
tree[rt].l=l,tree[rt].r=r;
tree[rt].val=INF;
if(l==r)
{
tree[rt].val=SA.height[l];
return ;
}
build(lson,l,mid);
build(rson,mid+,r);
tree[rt].val=min(tree[lson].val,tree[rson].val);
}
int query(int rt,int l,int r)
{
int mid=(tree[rt].l+tree[rt].r)/;
if(tree[rt].l==l&&tree[rt].r==r)return tree[rt].val;
if(r<=mid)return query(lson,l,r);
else
if(l>mid)return query(rson,l,r);
else
return min(query(lson,l,mid),query(rson,mid+,r));
} long long cal(int k,int n) //求出现k次以上的字符串的个数
{
long long ans=;
if(k==)
{
for(int i=;i<n;i++) ans+=(n-SA.sa[i]-SA.height[i]);
return ans;
}
int l=,r=+k-;
int pre=;
while(r<n)//处理全部长度为k-1的连续区间
{
int now=query(,l,r);
if(now>=pre) ans+=now-pre;//要注意减去上一个区间的贡献
pre=now;
l++,r++;
}
return ans;
}
int main()
{
while(scanf("%s",s)!=EOF)
{
int L,R;
scanf("%d%d",&L,&R);
int ls=strlen(s);
SA.build(s,);
build(,,ls-);
printf("%lld\n",cal(L,ls)-cal(R+,ls));
}
return ;
}
最新文章
- windows下Bullet 2.82编译安装(Bullet Physics开发环境配置)
- openstack changePassword
- spring aop advice
- P1443 马的遍历
- 161123、ssh scp 复制文件和文件夹
- Django模型修改及数据迁移
- 参照openRTSP写的一个RTSP client 加了一些注解
- Android在 Alertdialog对话框中点击消失?
- Unresolved reference issue in PyCharm
- Maven详解(八)------ 继承和聚合
- plsql启动提示监听服务无法连接
- Java由先序序列和中序序列还原二叉树
- C#生成唯一订单号
- R语言-增加图例
- FreeRTOS 中 systick 相关配置
- Java中类的构造方法
- Java NIO系列教程(二) Channel通道介绍及FileChannel详解
- C语言:指针实现输出梯形字符串
- 【LeetCode OJ】Swap Nodes in Pairs
- 汽车收费 C++ PTA