每日一题之 hiho229周 Same Letters In A Row

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014046022/article/details/84197449

描述
Litter Ho has a string of lowercase letters. He wants to re-order the letters so that the same letters are placed together in a row.

Unfortunately he can do at most K times of swaps. Each time he can only swap two letters. What is the maximum number of the consective same letters?

Assume the string is “bababbaa” and K = 1. By 1 swapping Little Ho can get “aabbbbaa”. “bbbb” has length 4 which is also the maximum number of the consective same letters Little Ho can get.

输入
The fist line contains an integer K. (1 <= K <= 100000)

The second line contain a string of lowercase letters. The length is no more than 100000.

输出
Output the answer.

样例输入
1
bababbaa
样例输出
4

题意:

给一个字符串,然后给定一个k,表示最多可以交换两个字符k次,问经过上述操作之后最大连续的字符长度是多少?

思路:

假设输入的字符串是s。

如果对于一个区间[i, j],可以通过不超过K次交换使得s[i]…s[j]都变成相同字符,我们就称区间[i, j]是可行的;否则称之为不可行的。

我们先考虑这样一个问题:对于给定区间[i, j],如何判断这个区间是否是可行的?

要解决上面的问题,我们可以逐次判断:

区间[i, j]是否可以变成全a? 区间[i, j]是否可以变成全b?… 区间[i, j]是否可以变成全z?

而对于一个确定的小写字符ch,区间[i, j]可以变成全ch的充分必要条件是:

(1)整个字符串s包含至少j-i+1个ch字符

(2)[i, j]区间中的非ch字符不超过K个

于是我们只要知道(1)这个字符串中’a’-‘z’的数目,我们用tot[]保存;以及(2)s[i] … s[j]中’a’-'z’的数目,我们用cnt[]保存。即可在O(26)=O(1)的复杂度判断[i, j]是否可行。

其中tot[]数组可以通过O(|s|)的预处理求出。

此外,我们知道区间的可行性具有某种单调性,即:

(1)如果[i, j]是不可行的,那么[i, j+1], [i, j+2], … 都是不可行的

(2)如果[i, j]是可行的,那么[i, j-1], [i, j-2], … 都是可行的

所以我们可以用双指针(滑动窗口)的思路去枚举极大可行区间。这样总共枚举O(|s|)数量的区间,并且当区间改变(从[i, j1]变为[i+1, j2])时,cnt[]数组的变化是均摊O(1)完成的。

总的时间复杂度是O(|s|)的。

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

int tot[30];
int cnt[30];

string s;

bool judge(int i, int j, int k) {
	for (int ch = 0; ch < 26; ++ch) {
		int tmp = j-i+1;
		int num = 0;
		if (tot[ch] >= tmp) {
			for (int ii = i; ii <= j; ++ii) {
				if (s[ii]-'a' != ch ) ++num;
			}
			if (num <= k) return true;	
		}
	}
	return false;
}

void solve(int n) {
	int len = s.length();
	memset(tot, 0, sizeof(tot));
	memset(cnt, 0, sizeof(cnt));

	for (int i = 0; i < len; ++i) {
		tot[s[i]-'a']++;
		cnt[s[i]-'a']++;
	}
	int res = 0;
	int i = 0;
	int j = 1;
	while(i < len && j < len) {
		if (judge(i, j, n)) {
			res = max(j-i+1, res);
			++j;
		}
		else {
			++i;
		}
	}
	cout << res << endl;
}

int main() {

	int k;
	cin >> k >> s;
	solve(k);

	return 0;
}

猜你喜欢

转载自blog.csdn.net/u014046022/article/details/84197449