描述
给你一个只由字母'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; } };