题目
一个长度为 n 的字符串 s,其中仅包含 ‘Q’, ‘W’, ‘E’, ‘R’ 四种字符。
如果四种字符在字符串中出现次数均为 n/4,则其为一个平衡字符串。
现可以将 s 中连续的一段子串替换成相同长度的只包含那四个字符的任意字符串,使其变为一个平衡字符串,问替换子串的最小长度?
如果 s 已经平衡则输出0。
Input
一行字符表示给定的字符串s
Output
一个整数表示答案
Input
QWER
Output
0
Input
QQWE
Output
1
Input
QQQW
Output
2
Input
QQQQ
Output
3
Note
1<=n<=10^5
n是4的倍数
字符串中仅包含字符 ‘Q’, ‘W’, ‘E’ 和 ‘R’.
思路
这题需要用到尺取法(双指针法)。
尺取法的使用条件为:
① 遍历一个连续的区间。
② 两个指针移动的方向一致。
将输入的字符串存在字符串s中,设字符串s的长度为len。统计字符串s中‘Q’、‘W’、‘E’、‘R’的个数,设个数分别为qNum、wNum、eNum、rNum。
对于给定的一段区间[L, R],设区间的长度为total。统计这个区间中‘Q’、‘W’、‘E’、‘R’的个数,设个数分别为qInSub、wInSub、eInSub、rInSub。设
qNotInSub = qNum - qInSub;
wNotInSub = wNum - wInSub;
eNotInSub = eNum - eInSub;
rNotInSub = rNum - rInSub;
maxNotInSub = MAX(qNotInSub, wNotInSub, eNotInSub, rNotInSub);
free = total - (maxNotInSub - qNotInSub) - (maxNotInSub - wNotInSub) - (maxNotInSub - eNotInSub) - (maxNotInSub - rNotInSub)。
若 free ≥0 且为 4 的倍数,则L++、minLen = MIN(minLen, total);否则R++。
循环上述过程直到遍历完整个字符串。
输出minLen。
代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
string s;
int qNum, wNum, eNum, rNum; // 记录4个字母在初始输入的字符串中的个数
int minLen;
int main()
{
while (cin >> s) {
int len = s.length();
qNum = 0, wNum = 0, eNum = 0, rNum = 0;
for (int i = 0; i < len; i++) { //统计4个字母在输入的字符串中的个数
switch (s[i])
{
case 'Q':
qNum++;
continue;
case 'W':
wNum++;
continue;
case 'E':
eNum++;
continue;
case 'R':
rNum++;
continue;
default:
continue;
}
}
if (qNum == len / 4 && wNum == len / 4 && eNum == len / 4 && rNum == len / 4) {
cout << 0 << endl;
continue;
}
int left = 0, right = 0, minLen = len + 1;
while (right < len && minLen>1) {
int qInSub = 0, wInSub = 0, eInSub = 0, rInSub = 0;
for (int i = left; i <= right; i++) {
switch (s[i])
{
case 'Q':
qInSub++;
continue;
case 'W':
wInSub++;
continue;
case 'E':
eInSub++;
continue;
case 'R':
rInSub++;
continue;
default:
continue;
}
}
int qNotInSub = qNum - qInSub;
int wNotInSub = wNum - wInSub;
int eNotInSub = eNum - eInSub;
int rNotInSub = rNum - rInSub;
int maxNotInSub = max(max(qNotInSub, wNotInSub), max(eNotInSub, rNotInSub));
int total = right - left + 1;
int free = total - (maxNotInSub - qNotInSub) - (maxNotInSub - wNotInSub) - (maxNotInSub - eNotInSub) - (maxNotInSub - rNotInSub);
if (free >= 0 && free % 4 == 0) {
if (minLen > total) minLen = total;
left++;
}
else {
right++;
}
}
cout << minLen << endl;
}
return 0;
}