题目描述
输入一个长度为4的倍数的字符串Q,字符串中仅包含WASD四个字母。
将这个字符串中的连续子串用同等长度的仅包含WASD的字符串替换,如果替换后整个字符串中WASD四个字母出现的频数相同,
那么我们称替换后的字符串是“完美走位”。求子串的最小长度。如果输入字符串已经平衡则输出0。
输入: 一行字符表示给定的字符串S
数据范围: 1<=n<=105且n是4的倍数,字符串中仅包含WASD四个字母。
输出: 整数表示答案
示例1
输入: WASDAASD
输出: 1
说明: 将第二个A替换为W,即可得到完美走位。
示例2
输入: AAAA
输出: 3
说明: 将其中三个连续的A替换为WSD,即可得到完美走位
示例3
输入
ASDW
输出
0
示例4
输入AASW
输出1
解题思路
深度优先搜索(DFS)
如图所示,区域m为可替换的子串,即求长度m的最小值,假设m的范围为[left,right),其中区域n1,和区域n2,称为域外,m称为域内,那么需要满足什么样的条件才能使得替换域内字符串之后能够达到完美走位呢?假设字符串总长度为L,则达到完美走位后WASD每个字符出现的次数均为avg=L/4,即将域内字符串替换后使得每个字符的出现次数均为avg,那么只需要满足域外两个子串中WASD每个字符出现次数不超过avg就可以了,一开始令left=0,right=L,然后left向右移动right向左移动,每次要么移动left要么移动right,当left=right时,m==0,到达死胡同,折返。当某次移动后域外某个字符出现的次数>avg在缩小m无意义,折返。
代码
#include <iostream>
#include <string>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
#include <numeric>
using namespace std;
int ans = 0;
string str;
int avg = 0;
int num[256] = { 0 };
void dfs(int left, int right, int numTmp[256])
{
if (right == left)
{
return;
}
if (numTmp['W'] <= avg && numTmp['A'] <= avg && numTmp['S'] <= avg && numTmp['D'] <= avg)
{
ans = ans > (right - left) ? (right - left) : ans;
numTmp[str[left]]++;
dfs(left + 1, right, numTmp);
numTmp[str[left]]--;
numTmp[str[right - 1]]++;
dfs(left, right - 1, numTmp);
numTmp[str[right - 1]]--;
}
else
{
return;
}
}
int main()
{
int left = 0, right = 0;
cin >> str;
int numTmp[256] = { 0 };
for (string::iterator it = str.begin(); it != str.end(); it++)
{
num[*it]++;
}
avg = str.size() / 4;
ans = str.size();
left = 0, right = str.size();
if (num['W'] == avg && num['A'] == avg && num['S'] == avg && num['D'] == avg)
{
ans = 0;
}
else
{
dfs(left, right, numTmp);
}
cout << ans << endl;
return 0;
}