记录67
#include<bits/stdc++.h>
using namespace std;
int main(){
string s1,s2,st1,st2;
int ans1=0,ans2=0;
cin>>s1>>s2;
int len1=s1.size();
int len2=s2.size();
int len=min(len1,len2);
for(int i=0;i<len;i++){
if(s1[i]==s2[len2-1]){
st1=s1.substr(0,i+1);//i+1是长度
st2=s2.substr(len2-i-1,i+1);
if(st1==st2) ans1=i+1;
}
}
for(int i=0;i<len;i++){
if(s2[i]==s1[len1-1]){
st2=s2.substr(0,i+1);
st1=s1.substr(len1-i-1,i+1);
if(st1==st2) ans2=i+1;
}
}
cout<<max(ans1,ans2);
return 0;
}
题目传送门
https://www.luogu.com.cn/problem/P2957
突破口
我们通过一个例子来理解题目。考虑下面的两个哞声:
moyooyoxyzooo
yzoooqyasdfljkamo第一个串的最后的部分
yzooo跟第二个串的第一部分重复。第二个串的最后的部分mo跟第一个串的第一部分重复。所以yzooo跟mo都是这 2 个串的重复部分。其中,yzooo比较长,所以最长的重复部分的长度就是 5。两个声音的重复部分有多长。
思路
- 字符串1从头开始找,字符串2从后开始找,相同的部分最大值用答案1保存
- 字符串2从头开始找,字符串1从后开始找,相同的部分最大值用答案2保存
- 取两个答案中大的那个值
代码简析
#include<bits/stdc++.h>
using namespace std;
int main(){
string s1,s2,st1,st2;
int ans1=0,ans2=0;
cin>>s1>>s2;
int len1=s1.size();
int len2=s2.size();
int len=min(len1,len2);
for(int i=0;i<len;i++){
if(s1[i]==s2[len2-1]){
st1=s1.substr(0,i+1);//i+1是长度
st2=s2.substr(len2-i-1,i+1);
if(st1==st2) ans1=i+1;
}
}
for(int i=0;i<len;i++){
if(s2[i]==s1[len1-1]){
st2=s2.substr(0,i+1);
st1=s1.substr(len1-i-1,i+1);
if(st1==st2) ans2=i+1;
}
}
cout<<max(ans1,ans2);
return 0;
}
string s1(字符串1),s2(字符串2),st1(切片1),st2(切片2);
int ans1=0(答案1),ans2=0(答案2); 👉 没有相同的长度就是0
int len1=s1.size(); 👉 字符串1的长度
int len2=s2.size(); 👉 字符串2的长度
int len=min(len1,len2); 👉 取最短的那一个作为循环的次数
for(int i=0;i<len;i++){} 👉 字符串开始遍历字符
if(s1[i]==s2[len2-1]){} 👉 找到跟字符串尾巴一样的地方
st1=s1.substr(0,i+1); 👉 字符串1从下标0开始切,得到切片1,i+1是长度
st2=s2.substr(len2-i-1,i+1); 👉 字符串2从尾巴往前数i+1开始切出来切片2
if(st1==st2) ans1=i+1; 👉 相同得到答案1
注意:切的长度是越来越长的,所以不用比较,有大的值自动更新
后面的for循环同理,只是前后的角色互换了
cout<<max(ans1,ans2); 👉 输出最长的那一个
补充
CSP-J 比赛中高频用到的字符串处理方法
一、基础存储与遍历(入门级必掌握)
这是字符串处理的前提,CSP-J 中优先推荐使用 C++ 的
string类(比字符数组char[]更易用、不易出错)。1. 存储方式
类型 用法示例 优点 注意点 string 类 string s = "abc123";自带成员函数,支持直接拼接 下标从 0 开始 字符数组 char s[100] = "abc123";兼容 C 语言,节省空间 需手动管理长度,易越界 2. 遍历方式(CSP-J 高频)
#include <iostream> #include <string> using namespace std; int main() { string s = "CSP-J2025"; // 方式1:下标遍历(最常用) for (int i = 0; i < s.size(); i++) { cout << s[i] << " "; // 输出:C S P - J 2 0 2 5 } cout << endl; // 方式2:范围for(C++11,比赛可用) for (char c : s) { cout << c << " "; // 效果同上 } return 0; }二、string 类核心成员函数(CSP-J 高频)
string类的内置函数是处理字符串的核心,以下是考试中最常考的函数:
函数 功能说明 示例(s = "abc123abc") size()/length()返回字符串长度(无符号整数) s.size()→ 9empty()判断字符串是否为空(空返回 true) s.empty()→ falses + t/append()字符串拼接 "abc" + "123"→ "abc123"substr(pos, len)截取子串:从 pos 开始,长度为 len(len 省略则到末尾) s.substr(3,3)→ "123";s.substr(6)→ "abc"find(str/char)查找子串 / 字符首次出现的下标,找不到返回 string::nposs.find("123")→ 3;s.find('x')→ nposrfind(str/char)查找子串 / 字符最后一次出现的下标 s.rfind("abc")→ 6erase(pos, len)删除子串:从 pos 开始,长度为 len s.erase(3,3)→ "abcabc"示例:子串查找与判断(CSP-J 常考题)
// 判断字符串s中是否包含子串"J2025" string s = "CSP-J2025"; if (s.find("J2025") != string::npos) { cout << "包含该子串" << endl; // 输出此句 } else { cout << "不包含" << endl; }三、字符级判断与转换(必考)
处理单个字符的类型判断、大小写转换,需包含
<cctype>头文件。
函数 功能说明 示例 isdigit(c)判断字符是否为数字 isdigit('5')→ trueisalpha(c)判断字符是否为字母 isalpha('A')→ trueislower(c)判断字符是否为小写字母 islower('b')→ trueisupper(c)判断字符是否为大写字母 isupper('C')→ truetolower(c)转小写(非字母不变) tolower('A')→ 'a'toupper(c)转大写(非字母不变) toupper('b')→ 'B'示例:统计字符串中的数字和字母数量
#include <iostream> #include <string> #include <cctype> using namespace std; int main() { string s = "CSP-J2025!@#"; int num_cnt = 0, alpha_cnt = 0; for (char c : s) { if (isdigit(c)) num_cnt++; else if (isalpha(c)) alpha_cnt++; } cout << "数字:" << num_cnt << endl; // 4 cout << "字母:" << alpha_cnt << endl; // 4 return 0; }四、字符串与数值的转换(高频)
CSP-J 常考 “字符串转数字”“数字转字符串”,需包含
<string>头文件,支持 C++11(比赛环境兼容)。
转换方向 函数 / 方法 适用场景 注意点 字符串→整数 stoi(s)转换 int 范围的整数(含负数) 超出 int 范围会抛异常 字符串→长整数 stoll(s)转换 long long 范围的大数 支持负数,适合大数场景 数值→字符串 to_string(num)支持 int/long long/double 万能转换,无需手动处理格式 示例:转换与计算
#include <iostream> #include <string> using namespace std; int main() { // 字符串转数字(支持负数) string s1 = "-12345", s2 = "9876543210123"; int n1 = stoi(s1); // -12345 long long n2 = stoll(s2); // 9876543210123 // 数字转字符串 int a = 678; long long b = -987654321; string s3 = to_string(a); // "678" string s4 = to_string(b); // "-987654321" cout << n1 + a << endl; // 666 cout << s3 + s4 << endl; // "678-987654321" return 0; }五、CSP-J 典型场景处理技巧
1. 回文判断(高频模拟题)
核心:双指针法,左右两端向中间对比字符。
bool isPalindrome(string s) { int l = 0, r = s.size() - 1; while (l < r) { if (s[l] != s[r]) return false; l++; r--; } return true; } // 调用:isPalindrome("abba") → true;isPalindrome("abc") → false2. 字符串分割(按分隔符,如空格、逗号)
CSP-J 常考 “按空格分割字符串为多个单词”,模拟遍历即可:
#include <iostream> #include <string> #include <vector> using namespace std; vector<string> split(string s, char sep = ' ') { vector<string> res; string temp; for (char c : s) { if (c == sep) { if (!temp.empty()) { // 避免空串(多个分隔符) res.push_back(temp); temp.clear(); } } else { temp += c; } } if (!temp.empty()) res.push_back(temp); // 处理最后一个单词 return res; } int main() { string s = "CSP-J 2025 入门级"; vector<string> words = split(s); for (string word : words) { cout << word << endl; // 输出:CSP-J、2025、入门级 } return 0; }3. 去除字符串中的空格 / 无用字符
核心:遍历筛选符合条件的字符,重新拼接。
string removeSpace(string s) { string res; for (char c : s) { if (c != ' ') res += c; // 保留非空格字符 } return res; } // 调用:removeSpace("a b c 1 2 3") → "abc123"六、避坑指南(CSP-J 易失分点)
- 下标越界:
string的下标从 0 开始,s.size()返回无符号整数,避免写i <= s.size()-1(当 s 为空时,s.size()-1会变成极大值),建议写i < s.size()。- 空字符串处理:操作前先用
empty()判断,避免对空串调用substr()、find()等函数。- 字符数组与 string 转换:若需用
printf输出string,需用s.c_str()转换为字符数组:printf("%s\n", s.c_str())。总结
- CSP-J 字符串处理优先使用
string类,核心掌握遍历、substr/find、字符判断 / 转换、数值转换四大类操作;- 典型场景(回文、分割、去空格)用 “双指针”“遍历筛选”“模拟拼接” 即可解决,无需复杂算法;
- 避坑重点是下标越界和空串处理,这是入门级比赛最易失分的细节。
1445

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



