2213: [Poi2011]Difference

本文介绍了一种算法,用于解决给定字符串中寻找连续片段的问题,使得片段内出现最频繁和最少频字母的数量之差达到最大。文章详细阐述了解决方案的思路与实现细节,并附带完整的代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2213: [Poi2011]Difference

Time Limit: 10 Sec   Memory Limit: 32 MB
Submit: 460   Solved: 161
[ Submit][ Status][ Discuss]

Description

A word consisting of lower-case letters of the English alphabet ('a'-'z') is given. We would like to choose a non-empty contiguous (i.e. one-piece) fragment of the word so as to maximise the difference in the number of occurrences of the most and the least frequent letter in the fragment. We are assuming that the least frequent letter has to occur at least once in the resulting fragment. In particular, should the fragment contain occurrences of only one letter, then the most and the least frequent letter in it coincide.

已知一个长度为n的由小写字母组成的字符串,求其中连续的一段,满足该段中出现最多的字母出现的个数减去该段中出现最少的字母出现的个数最大。求这个个数。

Input

The first line of the standard input holds one integer (1<=N<=1000000)() that denotes the length of the word. The second line holds a word consisting of lower-case letters of the English alphabet.

第一行,n
第二行,该字符串
1<=n<=1000000

Output

The first and only line of the standard output is to hold a single integer, equal to the maximum difference in the number of occurrences of the most and the least frequent letter that is attained in some non-empty contiguous fragment of the input word.

一行,表示结果

Sample Input

10
aabbaaabab

Sample Output

3
Explanation of the example: The fragment that attains the difference of 3 in the number of occurrences of a and b is aaaba.

HINT

Source

[ Submit][ Status][ Discuss]

可以尝试枚举一对答案字母,如,假设最终答案是由a,b组成的
那么,原串这么长其实并没有什么卵用,既然假设了是a和b,所以其它字符都是多余的
只要把a和b从原串中分离出来,新建一个串,这样,令a = 1,b = -1,答案就是权值和最大/最小的子串了
注意要判断当前选的子串是否都含有a,b什么什么的,,,,,,模拟一下就行
因为每个字符最多被调用26次,所以O(26*n)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<bitset>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;

const int maxn = 1E6 + 5;

int n,Ans,sum[maxn],Min[maxn],Max[maxn],typ[maxn];
char s[maxn];

vector <int> v[26];

void Work(int i,int j)
{
	int A,B,tot,lastA,lastB; 
	A = B = tot = lastA = lastB = 0;
	if (!v[i].size() || !v[j].size()) return;
	while (A < v[i].size() && B < v[j].size())
	{
		if (v[i][A] < v[j][B])
		{
			++tot; ++A; 
			sum[tot] = typ[tot] = 1;
		}
		else 
		{
			++tot; ++B;
			sum[tot] = typ[tot] = -1;
		}
	}
	while (A < v[i].size()) 
	{
		++tot; ++A; 
		sum[tot] = typ[tot] = 1;
	}
	while (B < v[j].size())
	{
		++tot; ++B;
		sum[tot] = typ[tot] = -1;
	}
	
	for (int i = 1; i <= tot; i++)
	{
		sum[i] += sum[i-1];
		Min[i] = min(Min[i-1],sum[i-1]);
		Max[i] = max(Max[i-1],sum[i-1]);
		if (typ[i] == 1)
		{
			lastA = i; if (!lastB) continue;
			Ans = max(Ans,sum[i] - Min[lastB]);
			Ans = max(Ans,Max[lastB] - sum[i]);
		}
		else
		{
			lastB = i; if (!lastA) continue;
			Ans = max(Ans,Max[lastA] - sum[i]);
			Ans = max(Ans,sum[i] - Min[lastB]);
		}
	}
}

int main()
{
	#ifdef DMC
		freopen("DMC.txt","r",stdin);
	#endif
	
	cin >> n; scanf("%s",s + 1);
	for (int i = 1; i <= n; i++) v[s[i] - 'a'].push_back(i);
	for (int i = 0; i < 26; i++)
		for (int j = i + 1; j < 26; j++)
			Work(i,j);
	cout << Ans;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值