B4039 [GESP202409 三级] 回文拼接

题目传送门

前言:这道题对于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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值