描述
给你一个只由字母'A'
和'B'
组成的字符串s
,找一个最长的子串,要求这个子串里面'A'
和'B'
的数目相等,输出该子串的长度。
- 这个子串可以为空。
s
的长度n
满足2<=n<=1000000
。
您在真实的面试中是否遇到过这个题?
是
样例
给定s="ABAAABBBA"
,返回8
。
解释:
子串 s[0,7] 和子串 s[1,8] 满足条件,长度为 8。
给定s="AAAAAA"
,返回0
。
解释:
s 中除了空字串,不存在 'A' 和 'B' 数目相等的子串。
最容易想到的方法就是暴力破译:
class Solution {
public:
/**
* @param S: a String consists of a and b
* @return: the longest of the longest string that meets the condition
*/
int getAns(string &S) {
// Write your code here
int maxsum=0;
for(int j=0;j<S.length();j++){
int asum=0;
int bsum=0;
for(int i=j;i<S.length();i++){
if(S[i]=='A') asum++;
else if(S[i]=='B') bsum++;
if(asum==bsum&&asum+bsum>maxsum) maxsum=asum+bsum;
}
}
return maxsum;
}
};
但这么做的话会超时。
所以需要一些取巧的办法,但我没有想出来,看了一位大佬的解法,遍历一遍字符串,用数组A和数组B分别保存 a的数量减去b的数量为i的最长前缀子串和最短前缀子串的长度,然后枚举每个i,更新答案,时间复杂度O(n)
class Solution {
public:
/*
* @param S: a String consists of a and b
* @return: the longest of the longest string that meets the condition
*/
int getAns(string &s) {
// write your code here
int n = s.length(), i;
vector<int> dpmax(2*n+1,0);
vector<int> dpmin(2*n+1,INT_MAX);
dpmin[n] = 0;
int sum = 0;
for(i = 0; i < n; i++) {
if(s[i] == 'A') {
sum++;
} else {
sum--;
}
dpmax[sum + n] = max(dpmax[sum + n], i + 1);
dpmin[sum + n] = min(dpmin[sum + n], i + 1);
}
int ans = 0;
for(i = -n; i <= n; i++) {
ans = max(ans, dpmax[i + n] - dpmin[n + i]);
}
return ans;
}
};