当前位置: 首页 > news >正文

【算法竞赛】回文字符串+思维模拟(蓝桥杯真题·回文字符串·代码清晰易懂)

回文在字符串中是一个非常常考的知识点,本题很考验思维和细节处理,可以作为回文问题的很好练习,后续也会总结一些字符串中回文的常见处理技巧和考法

目录

一、题目

二、思路解析

1. 允许的操作:

2.  我们将字符串划分为3部分:

3.  中间必须是回文:

4.  左侧是否匹配?

步骤如下:

5. 最终判断

三、知识点补充

1. 回文串判断

2. 字符串前缀/后缀提取

3. 模拟类字符串题常见技巧

四、代码


一、题目

P10905 [蓝桥杯 2024 省 C] 回文字符串 - 洛谷

二、思路解析

本题的关键在于理解允许的操作和回文串的定义:

1. 允许的操作:

只能在字符串的开头添加字符 'l''q''b'

这意味着我们可以"填补"原字符串的左边部分,而右边不能动

我们先思考:如果我们能在两端都插字符,那我们一定可以对称地填补每一侧,使其回文。

但由于限制只能在左边插,所以我们只能模拟“构造对称的左半边”:

2.  我们将字符串划分为3部分:

题目明确要求我们在左端添加字符的时候只能添加l ,q ,b 三种,所以:

(1)右端连续的l ,q ,b肯定可以被匹配,我们单独拎出来

(2)左端连续的l ,q ,b取决于在现有的(因为我们无法再在右端添加字符了)右端连续部分能否给它匹配,如果能则没问题,否则不合法

(3)剩余的中间部分必须得自己构成回文

故划分方式如下:

  • 左端(s1):开头连续的 'l''q''b' 字符

  • 右端(s3):结尾连续的 'l''q''b' 字符

  • 中间(s2):剩下的部分

3.  中间必须是回文:

中间部分 s2 是我们既不能删也不能改的核心部分。

如果 s2 不是回文串,那无论你怎么填左边都没用

4.  左侧是否匹配?

步骤如下:
  1. 检查左边连续的 lqb 部分(s1)是否能被右边的 lqb(s3)匹配掉

    • 因为我们只能在左边添加 lqb,所以我们不能用超过右边已有的字符

    • 换句话说:左边已有的 lqb 部分必须“能被右边覆盖”,才能形成对称

5. 最终判断

只有同时满足下面上面条件的字符串才能输出 “Yes”:

  1. 中间 s2 是回文串

  2. 左端已有的合法字符 s1 能被右端 s3 中的字符镜像匹配

三、知识点补充

1. 回文串判断

最常见的方法是双指针法:一个从左一个从右,逐字符比较

2. 字符串前缀/后缀提取

通过遍历 s 字符串前后,提取出所有的合法字符(即 lqb)

3. 模拟类字符串题常见技巧

  • 字符提取和分段:识别出具有意义的字符串片段

  • 子串处理:如 s.substr(start, len) 高效提取区间

  • 模拟构造:将操作的限制通过条件逻辑写代码

  • 双指针:处理对称性、滑动窗口、区间匹配等

四、代码

//只能在左侧连续添加,所以只能允许右端连续部分无法构成回文串
//且无法构成回文串的部分只包含l,q,b
//先去掉右端连续包含l,q,b的部分,看剩下的能否匹配 
//此时要注意左端连续部分有可能要和去掉的右端连续部分匹配
//所以还要判断左端连续l,q,b部分能否被匹配 
//注意:不是所有回文串都是按照先逆序再找公共子序列 
#include <iostream>
#include <cstring>
using namespace std;
int n;

//判断是否是回文串 
bool check(string s)
{
	int n=s.size();
	int i=0,j=n-1;
	while(i<j)
	{
		if(s[i]!=s[j]) return false;
		i++;
		j--;
	}
	return true;
}

int main()
{
	cin>>n;
	for(int m=1;m<=n;m++)
	{
		bool flag=true;
		
		string s;//原始字符串
		cin>>s;
		int n=s.size();
		
		string s1,s2,s3;//左端lqb连续部分,中间,右端lqb连续部分
		
		//左端连续lqb
		//i:停留在左端第一个不匹配的位置 
		int i,j;
		for(i=0;i<n;i++)
		{
			if(s[i]=='l'||s[i]=='q'||s[i]=='b') s1+=s[i];
			else break;
		}
		
		//右端连续lqb
		//j:停留在右端第一个不匹配的位置 
		for(j=n-1;j>=0;j--)
		{
			if(s[j]=='l'||s[j]=='q'||s[j]=='b') s3+=s[j];
			else break;
		}
		
		//substr:(i,len)
		//中间 
		s2=s.substr(i,j-i+1);
		//检查中间是否是回文串
		if(!check(s2)) flag=false;
		
		//检查左端已有连续lqb部分能否被右端完全匹配
		//s1和s3都倒序匹配 
		//指向s1 
		i=s1.size()-1;
		//指向s3
		j=s3.size()-1; 
		while(i>=0&&j>=0&&s1[i]==s3[j]){i--;j--;}
		if(i>=0) flag=false;//左端不能被右端完全匹配 
		
		//输出 
		if(flag) cout<<"Yes"<<endl;
		else cout<<"No"<<endl;
	}
	return 0;
}
  • 这道题考察了字符串模拟处理回文串判断双指针思想

  • 在保证中间部分为回文串的同时,我们还要关注边界拼接对称性

  • 注意细节:右端的连续部分既是参考标准,也是判断左端合法性的依据

如果你喜欢这种题解风格,欢迎关注我的博客/专栏,我会持续更新高质量的题解与算法思维讲解

http://www.dtcms.com/a/121821.html

相关文章:

  • 巧记英语四级单词 Unit3-上【晓艳老师版】
  • 【SpringCloud】从入门到精通(下)
  • TCP 与 UDP
  • Qt 开发时可以在函数内引用的头文件
  • 国网B接口协议调阅实时视频接口流程详解以及检索失败原因(电网B接口)
  • 蓝桥杯刷题总结 + 应赛技巧
  • MySQL表的增删查改(基础)
  • python学智能算法(九)|决策树深入理解
  • [前端]从人体结构看网页三要素:HTML、CSS 与 JavaScript
  • C#.NET模拟用户点击按钮button1.PerformClick自动化测试
  • 动手人形机器人(RL)
  • 去除Mysql表中的空格、回车、换行符和特殊字符
  • 淘宝API与小程序深度联动:商品详情页“一键转卖”功能开发
  • NO.83十六届蓝桥杯备战|动态规划-基础线性DP|台阶问题|最大子段和|传球游戏|乌龟棋(C++)
  • Elasticsearch 集群搭建
  • Vue3+Vite+TypeScript+Element Plus开发-10.多用户动态加载菜单
  • Hi Robot——大脑加强版的π0:基于「VLM的高层次推理+ VLA低层次任务执行」的复杂指令跟随及交互式反馈
  • Python标准库-copy
  • FairMOT复现过程中cython_bbox库问题
  • go游戏后端开发32:自摸杠处理逻辑
  • Elasticsearch中的基本全文搜索和过滤
  • Spring Boot应用中可能出现的Full GC问题
  • 滑动窗口(2)—最⼤连续1的个数III
  • git 查看某一文件夹下所有文件 修改记录
  • 深度学习总结(4)
  • LVGL开发指南
  • 如何构建并优化提示词?
  • 【LeetCode 热题100】73:矩阵置零(详细解析)(Go语言版)
  • 调用百度api实现黑白图像上色
  • Prompt_Engineering提示词工程(一)