版权声明:欢迎转载,请注明此博客地址。 https://blog.csdn.net/Ever_glow/article/details/82717261
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
Input has multiple test cases.
For each line, there is a string S, two integers A and B.
∑length(S)≤2×106,
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 后缀数组求出现K次不同字串的板子题,只需稍作修改,在容斥的时候,减去大于B次的就可以。 代码实现:
/*
Look at the star
Look at the shine for U
*/
#include<bits/stdc++.h>
#define ll long long
#define PII pair<int,int>
#define sl(x) scanf("%lld",&x)
using namespace std;
const int N = 200000+10;
int temp1[N],temp2[N],sam[N],c[N],lcp[N],num[N],Rank[N],len;
char s[N];
int dp[N][30];
void RMQ(int* arr, int n)
{
for(int i = 0;i < n;++i) dp[i][0] = arr[i];
for(int j = 1;(1<<j) <= n;++j)
for(int i = 0;i+(1<<j)-1<n;++i)
dp[i][j] = min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
ll ask(int l,int r)
{
int k = 0;
while((1<<(k+1))<=r-l+1) ++k;
ll ans = min(dp[l][k],dp[r-(1<<k)+1][k]);
return ans;
}
bool judge(int* arr,int x,int y,int l)
{
if(arr[x] == arr[y] && arr[x+l] == arr[y+l]) return true;
else return false;
}
ll query(int l,int r)
{
if (l == r) return len-sam[r];
return ask(l+1,r);
}
void init(int n,int m)
{
++n;
int i,j,p,*x = temp1,*y = temp2;
for(i = 0;i < m;++i) c[i] = 0;
for(i = 0;i < n;++i) c[x[i] = num[i]]++;
for(i = 1;i < m;++i) c[i] += c[i-1];
for(i = n-1;i;--i) sam[--c[x[i]]] = i;
for(j = 1;j <= n;j <<= 1)
{
p = 0;
for(i = n-j; i<n;++i) y[p++] = i;
for(i = 0;i < n;++i)
if(sam[i] >= j)
y[p++] = sam[i] - j;
for(i = 0;i < m;++i) c[i] = 0;
for(i = 0;i < n;++i) c[x[y[i]]]++;
for(i = 1; i < m;++i) c[i] += c[i-1];
for(i = n-1;i;--i)
sam[--c[x[y[i]]]] = y[i];
swap(x,y);
p = 1;
x[sam[0]] = 0;
for (i = 1;i < n;++i)
{
if(judge(y,sam[i-1],sam[i],j)) x[sam[i]] = p-1;
else x[sam[i]] = p++;
}
if(p >= n) break;
m = p;
}
int k = 0;
n--;
for(i = 0;i <= n;++i) Rank[sam[i]] = i;
for(i = 0;i < n;++i)
{
if(k)--k;
j = sam[Rank[i]-1];
while(num[i+k] == num[j+k]) ++k;
lcp[Rank[i]] = k;
}
}
int main()
{
int t,k,x,i,j;
while(~scanf("%s%d%d",s,&k,&x))
{
len = strlen(s);
for(i = 0;i <= len;i++)
{
Rank[i] = lcp[i] = sam[i] = 0;
}
for (i = 0; i < len; ++i) num[i] = s[i]-'A'+1;
num[len] = 0;
init(len,30);
RMQ(lcp,len+1);
ll ans = 0;
for (i = 1;i+k-1 <= len;i++)
{
ans += query(i,i+k-1); //至少k个
if(i-1 > 0) ans -= query(i-1,i+k-1);
if(i+x <= len) ans -= query(i,i+x);
if(i-1 > 0 && i+x <= len) ans += query(i-1,i+x);
}
printf("%lld\n",ans);
}
return 0;
}