CF144C解题报告
CF144C 解题报告
题意
给两个字符串 \(s\) 和 \(t\),让你求 \(s\) 好的子串的个数。
对于 \(s_1\) 和 \(s_2\),若 \(s_1\) 交换字母顺序后可以得到 \(s_2\),即 \(s_1\) 和 \(s_2\) 拥有的字母相同且相同字母的个数相同,则我们称之为 \(s_1\) 相似于 \(s_2\)。
分析
由题意得,可以记录每个字符出现了几次。这里可以记录 \(s\) 的字串每个字母出现了多少次,再比较 \(t\) 中的字母,若相同,则满足条件。
这里可以优化一下,直接记录 \(t\) 中每一个字符的出现次数减去 \(s\) 中对应字符的出现个数 \(a_i\),如果 \(a_i \ge 0\) 那么 \(t\) 中出现的字符的次数一定比 \(s\) 中的多。显然,如果每一个字符都是 \(t\) 比 \(s\) 多,那么 \(s\) 在补全 ?
之后字符出现次数一定与 \(t\) 相同。
不断挪动 \(s\) 中对应的区间,维护 \(a\) 数组,实时更新答案。
一个特判,如果 \(s\) 比 \(t\) 短,那么一定不可能有合法情况。
代码
#include<bits/stdc++.h>
using namespace std;
int cnt;
int a[26];
string s, t;
int main(){
cin >> s >> t;
if (s.size() < t.size()) return cout << "0", 0;
for (int i = 0; i < t.size(); i++){//初始化a
a[t[i] - 'a']++;
if (s[i] != '?') a[s[i] - 'a']--;
}
int l = 0, r = t.size() - 1;
while (r < s.size()){
int i = 0;
while (i < 26 && a[i] >= 0) i++;//判断t中字符的出现次数的是否大于s
if (i == 26) cnt++;//满足条件,全部大于等于
if (r == s.size() - 1) break;
if (s[l] != '?') a[s[l] - 'a']++;//挪动窗口,维护a
if (s[r + 1] != '?') a[s[r + 1] - 'a']--;
l++, r++;
}
cout << cnt;
return 0;
}