记录57
#include<bits/stdc++.h>
using namespace std;
int main(){
int T,n,m,cnt=0;
string s1,s2,s3;
cin>>T;
while(T--){
cin>>n>>m;
cin>>s1>>s2;
cnt=0;
for(int i=0;i<n;i++) if(s1[i]>='A'&&s1[i]<='Z') s1[i]+='a'-'A';
for(int i=0;i<m;i++) if(s2[i]>='A'&&s2[i]<='Z') s2[i]+='a'-'A';
for(int i=0;i<=m-n;i++){//i+n-1<=m-1的变形
s3=s2.substr(i,n);
if(s1==s3){
cnt++;
}
}
cout<<cnt<<endl;
}
return 0;
}
题目传送门
https://www.luogu.com.cn/problem/P8835
突破点
给定 T 组询问,每次给定 2 个长度为 n,m 的只含英文字母的字符串 a,b,求 a 在 b 中的出现次数,相同字符不区分大小写。注意 a 是 b 中连续子序列。
思路
- 将字符串所有的大写转换成小写
- 将a字符串轮流比较b字符的每一段
代码简析
#include<bits/stdc++.h>
using namespace std;
int main(){
int T,n,m,cnt=0;
string s1,s2,s3;
cin>>T;
while(T--){
cin>>n>>m;
cin>>s1>>s2;
cnt=0;
for(int i=0;i<n;i++) if(s1[i]>='A'&&s1[i]<='Z') s1[i]+='a'-'A';
for(int i=0;i<m;i++) if(s2[i]>='A'&&s2[i]<='Z') s2[i]+='a'-'A';
...
return 0;
}
int T(数据组数),n(字符串a的长度),m(字符串b的长度),cnt=0(连续子序列出现次数);
string s1(字符串a),s2(字符串b),s3(字符串中的连续子序列);
两个for循环将所有大写字符转换为小写
#include<bits/stdc++.h>
using namespace std;
int main(){
int T,n,m,cnt=0;
string s1,s2,s3;
cin>>T;
while(T--){
cin>>n>>m;
cin>>s1>>s2;
cnt=0;
for(int i=0;i<n;i++) if(s1[i]>='A'&&s1[i]<='Z') s1[i]+='a'-'A';
for(int i=0;i<m;i++) if(s2[i]>='A'&&s2[i]<='Z') s2[i]+='a'-'A';
for(int i=0;i<=m-n;i++){//i+n-1<=m-1的变形
s3=s2.substr(i,n);
if(s1==s3){
cnt++;
}
}
cout<<cnt<<endl;
}
return 0;
}
for(int i=0;i<=m-n;i++){} 👉 连续子序列的开始位置
解释:因为i是开始位置,长度为n,去掉开始的头i,长为n-1,a字符串尾巴最多到i+n-1,又因为b字符串尾巴位置最多到m-1(因为从0开始),所以i+n-1<=m-1,即i<=m-n。
s3=s2.substr(i,n); 👉 得到连续子序列
if(s1==s3){cnt++;} 👉 如果连续子序列跟字符串a相同,计数统计
补充
字符串处理函数完全汇总
一、C风格字符串函数(<cstring>
函数 用途 时间复杂度 竞赛示例 ⚠️ 陷阱 **strlen() ** 求长度(到'\0') O(n) int len = strlen(s);无'\0'越界 ** strcpy()** 复制字符串 O(n) strcpy(dest, src);dest必须够大 strcat() 拼接字符串 O(n) strcat(s, "abc");易溢出 strcmp() 比较字典序 O(n) if (strcmp(a, b) < 0)返回int,非bool sprintf() 格式化到char[] O(n) sprintf(buf, "%d", x);缓冲区溢出 sscanf() 从char[]解析 O(n) sscanf(buf, "%d", &x);解析失败无警告 strchr() 找字符首次出现 O(n) char* p = strchr(s, 'a');未找到返回NULL strstr() 找子串首次出现 O(n) char* p = strstr(s, "abc");未找到返回NULL strtok() 分割字符串 O(n) char* tok = strtok(s, ",");破坏原串 CSP-J推荐:少用C函数,除非必须与
scanf/printf混用!
二、C++ string类成员函数(<string>
函数 用途 时间复杂度 竞赛示例 ⚠️ 陷阱 size()/length() 求长度 O(1) int len = s.size();无 operator[] 随机访问 O(1) s[i] = 'a';越界不检查 at() 安全访问 O(1) s.at(i)越界抛异常(不用) substr(pos, len) 取子串 O(len) s.substr(1, 3)返回新string find(str) 找子串位置 O(n) size_t pos = s.find("abc");未找到返回 string::nposrfind(str) 反向查找 O(n) s.rfind("abc")同上 replace(pos, len, str) 替换 O(n) s.replace(0, 2, "xx")会改变原串 insert(pos, str) 插入 O(n) s.insert(0, "abc")少用,慢 erase(pos, len) 删除 O(n) s.erase(0, 2)少用,慢 append(str) 尾部拼接 O(n) s.append("abc")等价于 +=push_back(c) 尾部加字符 O(1) s.push_back('a')推荐 pop_back() 尾部删字符 O(1) s.pop_back()推荐 c_str() 转C字符串 O(1) printf("%s", s.c_str())必须转换 data() 字符指针 O(1) s.data()不保证 \0clear() 清空 O(1) s.clear()size变0 empty() 判空 O(1) if (s.empty())推荐 CSP-J推荐:首选
size()、push_back()、substr()、find()
三、C++算法库函数(<algorithm><cctype>
函数 用途 时间复杂度 竞赛示例 ⚠️ 陷阱 sort() 排序 O(n log n) sort(s.begin(), s.end())改变原串 reverse() 翻转 O(n) reverse(s.begin(), s.end())无 isalpha(c) 判字母 O(1) if (isalpha(s[i]))需包含 <cctype>isdigit(c) 判数字 O(1) if (isdigit(s[i]))同上 islower(c) 判小写 O(1) if (islower(s[i]))同上 isupper(c) 判大写 O(1) if (isupper(s[i]))同上 tolower(c) 转小写 O(1) c = tolower(s[i])返回int,需转char toupper(c) 转大写 O(1) c = toupper(s[i])同上 unique() 去重相邻 O(n) s.erase(unique(s.begin(), s.end()), s.end())只去相邻重复 next_permutation() 下一个排列 O(n) while(next_permutation(s.begin(), s.end()))需先排序 CSP-J推荐:**
isalpha(),isdigit(),tolower()高频使用 **
四、C++11/14/17新特性(CSP-J可用)
函数 用途 竞赛示例 备注 ** stoi(s)** string转int int x = stoi("123")错误抛异常 stol(s) string转long long x = stol(s)- stoll(s) string转long long ll x = stoll(s)推荐 to_string(x) 数字转string string s = to_string(123)推荐 ostringstream 流式拼接 ostringstream oss; oss << a << b;比 +快CSP-J推荐:
stoll()+to_string()处理数字字符串转换
五、性能对比与竞赛建议
速度排行(快→慢)
O(1)操作:size(), push_back(), c_str() ↓ O(1) per char: operator[], at() ↓ O(n)简单:reverse(), isalpha() ↓ O(n)复杂:sort(), unique() ↓ O(n*m):频繁insert/erase(绝对避免)CSP-J金牌模板
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); // 1. 输入(string) string s; cin >> s; // 自动处理空格 // 2. 遍历(范围for) for (char c : s) { if (islower(c)) { // 判断 c = toupper(c); // 转换 } } // 3. 查找(find) size_t pos = s.find("abc"); if (pos != string::npos) { s.replace(pos, 3, "xyz"); // 替换 } // 4. 排序(sort) sort(s.begin(), s.end()); // 5. 输出 cout << s << endl; // 或printf("%s", s.c_str()); return 0; }
六、一句话总结
CSP-J中:string用
size()+push_back()+find()+sort(),字符用isalpha()+tolower(),转数字用stoll(),转字符串用to_string(),C函数少用,混用printf记得c_str()。
1055

被折叠的 条评论
为什么被折叠?



