CodeForces 386C. Diverse Substrings (字符串+双指针)

CodeForces 386C. Diverse Substrings (字符串+双指针)_第1张图片

d(s)为字符串s的字符种类个数,求d(s) 的值,以及s的子串中,字符种类为1,2,...,d(s) 的分别有多少个。

CF上的标签是"dp" 和 “two pointers"。

第二次遇到的双指针的题,上一次遇到是CF的514D。这个的双指针比514D的要稍微麻烦一些,实际上是”三指针“。

双指针主要用于,需要遍历某个区间的所有子区间 的时候,直接枚举左右边界的话时间复杂度是O(n^2),用双指针的话,是O(n)。

对于这道题而言,对 k =1,2,..,d(s)  分别计算 t(k)。

首先枚举区间左端点L,R1为保证d ( [L,R] )=k 的最小R值,R2为保证d ( [L,R] ) > k  的最小R值,这样的话,以L为左端点的区间中,字符种数为k的就有R2-R1种。

双指针能简化运算就在于,L+1所对应的R1和R2 一定大于等于原先L对应的R1和R2,所以,计算新的R1和R2的时候,只需要从原来的R1,R2往后加就行了,

这样就变成了L,R1,R2这三个指针的单调递增,于是总时间复杂度也就变成O(n)的了。

有一个例外情况,当[L,R1]的字符种数小于k的时候,若R1< n 则R1++,所以,若出现 [L,R1]的字符种数小于k  这种情况时,一定是R1=n,R2=n+1;

这时,由于答案不再是R2-R1种,而是R2-R1-1种,所以其实表达式应该是 ANS+=R2-R1- (R1==n);       

 当然,(R1==n)等价于    ( [L,R1]的字符种数小于k)     在我的代码中即为(M1.m<k)


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#define maxn 300007
using namespace std;
struct Mark{//存储状态的结构体
	int cnt[26];
	int m;
	Mark(){memset(cnt,0,sizeof(cnt));m=0;}
};
string str;
int n;
long long d[27];
int getK(Mark m){
	int ANS=0;
	for(int i=0;i<26;++i) ANS+=(m.cnt[i]>0);
	return ANS;
}
void T(int k){//求 T(k) 
	int R1=1,R2=1;//[L,[R1..R2)]为以L开始的区间 
	Mark M1,M2;//区间[L,R1]和 [L,R2] 的状态 
	M1.cnt[str[0]-'a']++;M1.m=1;M2=M1;
	for(int L=1;L <=n;++L){//枚举左端点 
		//更新 M1,M2 使之对应区间 [L,R1]和[L,R2] (这里的L是新的L。而M1,M2对应的是旧L的区间)
		if(L>1){ 
			M1.cnt[str[L-2]-'a']--;if(!M1.cnt[str[L-2]-'a']) M1.m--;
			M2.cnt[str[L-2]-'a']--;if(!M2.cnt[str[L-2]-'a']) M2.m--;
		}
		//计算新的R1,R2 
		while(M1.m < k&&R1 < n){if(!M1.cnt[str[R1]-'a']) M1.m++;M1.cnt[str[R1++]-'a']++;}
		while(M2.m <=k&&R2 <=n){if(!M2.cnt[str[R2]-'a']) M2.m++;M2.cnt[str[R2++]-'a']++;}
		//累加计算结果 
		d[k]+=R2-R1-(M1.m <k);//printf("d[%d]+=%d (L=%d  R1=%d R2=%d)\n",k,R2-R1,L,R1,R2);
	}
}
int main(void)
{
	while(cin>>str){
		Mark M; 
		n=str.length();
		for(int i=0;i<n;++i) M.cnt[str[i]-'a']++;
		memset(d,0,sizeof(d));
		int D=getK(M);
		for(int i=1;i<=D;++i){T(i);}
		printf("%d\n",D);
		for(int i=1;i<=D;++i){
			cout<<d[i]<<endl;
		}
	}
return 0;
}


你可能感兴趣的:(字符串,codeforces)