CodeForces - 1307C Cow and Message(思维)

题目链接:点击查看

题目大意:给出一个字符串,在这个题目中的子序列定义为,出现次数必须是等差数列的序列,如:aaabb的其中一个子序列就是aab,其出现的位置是1 3 5,呈等差数列,现在问,在这个题目中出现次数最多的子序列,出现的次数是多少

题目分析:又是一道读完题后猜出正解,但因为实现一直WA的题目,其实读完题后,再参照样例,可以猜个差不多的结论,那就是对答案有贡献的子序列,长度不是 1 就是 2 ,因为自己举了几个例子后发现,如果存在一个长度大于 2 的子序列,那么其长度必定可以拆成长度为 1 的或者长度为 2 的,这样一来我们就发现等差数列的这个条件也就变成了烟雾弹,因为长度为 1 和长度为 2 的子序列无论如何组合,都肯定是等差数列

有了上面的猜想就不难实现了,长度为 1 的子序列就是统计一下每个字母出现的次数,取最多的那个字母就行了,而长度为二的子序列,我用了一种比较笨的方法,那就是直接暴力枚举两个字母,时间复杂度是 n * 26 * 26 ,不过也无伤大雅,枚举的这两个字母是不相同的,而相同的我们可以利用排列组合 C( mmax , 2 ) 计算得出,这里的 mmax 就是刚才求出的,出现次数最多的字母了

代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
     
typedef long long LL;
    
typedef unsigned long long ull;
     
const int inf=0x3f3f3f3f;

const int N=1e5+100;
 
char s[N];

LL cnt[N][26];//前缀和
 
int main()
{
//#ifndef ONLINE_JUDGE
//  freopen("input.txt","r",stdin);
//    freopen("output.txt","w",stdout);
//#endif
//  ios::sync_with_stdio(false);
	scanf("%s",s+1);
	int len=strlen(s+1);
	for(int i=1;i<=len;i++)
	{
		for(int j=0;j<26;j++)
			cnt[i][j]=cnt[i-1][j];
		cnt[i][s[i]-'a']++;
	}
	LL mmax=0;
	for(int i=0;i<26;i++)
		mmax=max(mmax,cnt[len][i]);
	mmax=max(mmax,(mmax-1)*mmax/2);
	for(int j=0;j<26;j++)
		for(int k=0;k<26;k++)
		{
			if(j==k)
				continue;
			LL temp=0;
			for(int i=1;i<=len;i++)
				if(s[i]==char(k+'a'))
					temp+=cnt[i][j];
			mmax=max(mmax,temp);
		}
	printf("%lld\n",mmax);
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
    return 0;
}

 

你可能感兴趣的:(思维,CodeForces上分,思维)