codeforces 386C Diverse Substrings
https://codeforces.com/problemset/problem/386/C
题意:
对于字符串 s s s有多样性 d ( s ) d(s) d(s)表示字符串里面不同字符的个数,然后k从1到 d ( s ) d(s) d(s),问s有多少个的子串的多样性刚好等于k。
题解:
本来想找题字符串题做做的,结果这题是个披着字符串皮的技巧题。
对于某个值k来说,单独求它的子串有多少个其实不好处理,但对于多样性
>
=
k
>=k
>=k有多少个子串却很好求,可以用尺取法在
O
(
n
)
O(n)
O(n)时间内处理出来。记
f
(
k
)
f(k)
f(k)为多样性
>
=
k
>=k
>=k的子串的个数,那答案很明显就是
f
(
k
+
1
)
−
f
(
k
)
f(k+1)-f(k)
f(k+1)−f(k)。怎么尺取具体看代码。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+5;
const int mod=1e9+7;
#define pb push_back
#define fi first
#define se second
#define all(x) (x).begin(),(x).end()
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,a,n) for (int i=n;i>=a;i--)
typedef long long ll;
typedef double db;
typedef vector<int> vi;
typedef pair<int,int> pii;
ll qpow(ll a,ll b){ll ans=1;a%=mod;assert(b>=0);for(;b;b>>=1){if(b&1)ans=ans*a%mod;a=a*a%mod;}return ans;}
ll gcd(ll a,ll b){return b>0?gcd(b,a%b):a;}
int n,m,T;
char s[maxn];
ll dp[30];
int cnt[30];
int add(int c){
int res=0;
if(!cnt[c]) res=1;
return res;
}
int del(int c){
int res=0;
if(cnt[c]-1==0) res=-1;
return res;
}
void gao(int t){
memset(cnt,0,sizeof cnt);
int l=1,r=0,num=0;
for(int i=1;i<=n;i++){
num+=add(s[i]-'a');
cnt[s[i]-'a']++;
if(num==t){
r=i;
break;
}
}
ll res=0;
for(int i=r;i<=n;i++){
while(l<i&&num+del(s[l]-'a')>=t){
num+=del(s[l]-'a');
cnt[s[l]-'a']--;
l++;
}
res+=l;
if(i==n)continue;
num+=add(s[i+1]-'a');
cnt[s[i+1]-'a']++;
}
dp[t]=res;
}
ll ans[30];
int main(){
cin>>s+1;
n=strlen(s+1);
m=0;
for(int i=1;i<=n;i++){
m+=add(s[i]-'a');
cnt[s[i]-'a']++;
}
for(int i=m;i>=1;i--){
gao(i);
ans[i]=dp[i]-dp[i+1];
}
cout<<m<<endl;
for(int i=1;i<=m;i++){
cout<<ans[i]<<endl;
}
return 0;
}
/*
*/