window.cnblogsConfig = {//可以放多张照片,应该是在每一个博文上面的图片,如果是多张的话,那么就随机换的。 homeTopImg: [ "https://cdn.luogu.com.cn/upload/image_hosting/clcd8ydf.png", "https://cdn.luogu.com.cn/upload/image_hosting/clcd8ydf.png" ], }

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;
}
posted @ 2024-01-18 07:50  CCF_IOI  阅读(13)  评论(0)    收藏  举报