题目描述:给出两个相同的由字符a和b构成的字符串,定义它们的距离为对应位置不同的字符的数量。如串“aab”与串“aba”的距离是2;串“ba”与串“aa”的距离是1;串“aba”与串”aba”的距离是0。下面给出两个字符串S和T,其中S的长度不小于T的长度。我们用|S|表示S的长度,用|T|表示T的长度,那么在S中一共有|S|-|T|+1个与T长度相同的子串,现在你需要计算T串与这些|S|-|T|+1个子串的距离的和。
输入:
第一行是字符串S
第二行是字符串T
S和T均由字符a和b组成,1<=|T|<=|S|<=10^5
例如:
输入
aba
aab
输出:
2
解法一:暴力破解
时间复杂度O(M*N),暴力破解只能通过70%。
#include<iostream>
#include<string>
using namespace std;
int main() {
string s, t;
cin >> s >> t;
int slen = s.size();
int tlen = t.size();
int res = 0;
for (int i = 0; i < slen - tlen + 1; i++) {
int count = 0;
for (int j = 0; j < t.size(); j++) {
if (t[j] != s[j+i])
count++;
}
res += count;
}
cout << res << endl;
return 0;
}
解法二:
思路:关注到只有a、b两个字符,暴力破解不论有几种字符都能解决。
第一步,计算S中从第一个字符到第n个字符中的a(或b)的个数。
第二步,T中第i个字符只会跟S中的第i~(i+d)个字符进行比较,计算出所有这些比较的距离之和,并以这种方式遍历这个字符串T。
时间复杂度O(M+N)
#include<iostream>
#include<string>
using namespace std;
int pre[111111];
int main(){
string s, t;
cin >> s >> t;
memset(pre, 0, sizeof(pre));
for (int i = 0; i < s.size(); ++i){
pre[i + 1] = s[i] == 'a' ? pre[i] + 1 : pre[i];
}
int ans = 0, d = s.size() - t.size() + 1;
for (int i = 0; i < t.size(); ++i){
if (t[i] == 'a'){
ans += d - (pre[i + d] - pre[i]);//d-(pre[i+d] - pre[i])计算i-(i+d)中b的个数
}
else{
ans += pre[i + d] - pre[i];
}
}
cout << ans << endl;
}