前言:这道题对于c++从初学者来说是比较复杂的,涉及到字符串的处理以及string类型的函数。
题解:
实现的问题:
1.如何把一个字符串分成两部分。
2.如何截取另一个字符串。
3.如何判断是否为回文字符串。
思路:
1.对于第一个问题而言,我们可以从头到尾遍历一遍字符串,然后根据字符串当前的下标把字符串分为两个部分。但是出现了新的问题,那就是如何存储前后两个字符串?
那么我们可以这么想:
(1).对于前面的字符串,我们可以边遍历边添加字符。
(2).对于后面的字符串,我们可以用s.substr()来截取。
s.substr()的用法:
s.substr(node,len);
//其中,node是截取字符串的开始位置,而len则是截取字符串的长度。
所以,我们可以这么存储:
string s1,s2;//s1存储前面的字符串,s2存储后面的字符串。
int len=s.size();//获取总字符串的长度。
int len2=0;//第一个字符串的长度
for(int i=0;i<s.size();i++){//从头到尾遍历第一个字符串
s1+=s[i];//添加第一个字符串
len2=s1.size();//实时更新第一个字符串的长度
s2=s.substr(i+1,len-len2);//截取后面的字符串
}
2.对于第二个问题而言,可以用s.substr()存储(在上方已经说过)。
这里主要再次介绍一下:
substr()
是 C++ 字符串 (std::string
) 的一个成员函数,用于从字符串中提取子串。以下是它的全部用法:
基本用法:
#include <string>
#include <iostream>
int main() {
std::string s = "Hello, World!";
// 用法1: s.substr(pos)
// 从位置pos开始到字符串末尾的子串
std::string sub1 = s.substr(7); // "World!"
// 用法2: s.substr(pos, count)
// 从位置pos开始,长度为count的子串
std::string sub2 = s.substr(0, 5); // "Hello"
std::cout << sub1 << std::endl;
std::cout << sub2 << std::endl;
return 0;
}
参数说明:
-
pos
- 要包含的子串的第一个字符的位置-
如果
pos
等于字符串长度,则返回空字符串 -
如果
pos
大于字符串长度,则抛出std::out_of_range
异常 -
默认值为 0(如果省略第一个参数)
-
-
count
- 子串的长度-
如果
count
大于s.size() - pos
,则返回[pos, s.size())
的子串 -
如果省略或为
std::string::npos
,则返回[pos, s.size())
的子串
-
更多示例 :
#include <string>
#include <iostream>
int main() {
std::string s = "Programming";
// 从位置3开始到末尾
std::cout << s.substr(3) << std::endl; // "gramming"
// 从位置0开始,长度4
std::cout << s.substr(0, 4) << std::endl; // "Prog"
// 从位置3开始,长度5
std::cout << s.substr(3, 5) << std::endl; // "gramm"
// 长度超过字符串长度
std::cout << s.substr(5, 100) << std::endl; // "amming" (只到字符串末尾)
// 省略所有参数 - 从位置0开始到末尾
std::cout << s.substr() << std::endl; // "Programming"
// 边界情况
std::cout << s.substr(s.size()) << std::endl; // "" (空字符串)
try {
// 抛出异常的例子
std::cout << s.substr(100) << std::endl;
} catch (const std::out_of_range& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
return 0;
}
注意事项:
(1).substr()
不会修改原字符串,而是返回一个新的字符串
(2).如果 pos
超出字符串长度,会抛出 std::out_of_range
异常
(3).这是一个时间复杂度为 O(n) 的操作,因为它需要复制字符到新字符串
3.对于第三个问题而言,建议从未到头遍历一遍字符串,使用新的字符串逐个添加字符即可。然后判断这两个字符是否相同即可。
bool check(string str){
string revers_str;
for(int i=str.size()-1;i>=0;i--){//从尾到头遍历
revers_str+=str[i];//添加字符
}
//判断
if(str==revers_str){
return 1;
}
else{
return 0;
}
}
AC CODE(全部):
#include<bits/stdc++.h>
using namespace std;
bool check(string str){
string revers_str;
for(int i=str.size()-1;i>=0;i--){
revers_str+=str[i];
}
if(str==revers_str){
return 1;
}
else{
return 0;
}
}
int main(){
int n;
scanf("%d",&n);
while(n--){
string s;
cin>>s;
string s1,s2;
int len=s.size();
int len2=0;
bool flag=0;
for(int i=0;i<s.size();i++){
s1+=s[i];
len2=s1.size();
s2=s.substr(i+1,len-len2);
if(len-len2>=2&&len2>=2&&check(s1)==1&&check(s2)==1){
printf("Yes\n");
flag=1;
break;
}
}
if(flag==0){
printf("No\n");
}
}
return 0;
}