蓝桥杯基础题 字符串处理(持续更新中)

目录

标题统计

罗马数字

删除字符

扫雷游戏

潜伏者

ISBN 号码

字符串的展开

FBI树


标题统计

https://www.lanqiao.cn/problems/325/learning/

题目描述

凯凯刚写了一篇美妙的作文,请问这篇作文的标题中有多少个字符?

注意:标题中可能包含大、小写英文字母、数字字符、空格和换行符。统计标题字符数时,空格和换行符不计算在内。

输入描述

输入文件只有一行,一个字符串 s\ (1 \leq |s| \leq 5)s (1≤∣s∣≤5)。

输出描述

输出只有一行,包含一个整数,即作文标题的字符数(不含空格和换行符)。

输入输出样例

示例

输入

Ca 45

输出

4

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M
#include<bits/stdc++.h>
using namespace std;
int main(){
	string str;
	int count = 0;
	getline(cin,str);    //获取一行字符串,包括空格
	for(int i =0;i<str.size();i++){
		if(str[i]!=' ')
		count++;
	}
	cout<<count;
} 

罗马数字

https://www.lanqiao.cn/problems/276/learning/

题目描述

古罗马帝国开创了辉煌的人类文明,但他们的数字表示法的确有些繁琐,尤其在表示大数的时候,现在看起来简直不能忍受,所以在现代很少使用了。之所以这样,不是因为发明表示法的人的智力的问题,而是因为一个宗教的原因,当时的宗教禁止在数字中出现 0 的概念!

罗马数字的表示主要依赖以下几个基本符号:

I 1

V 5

X 10

L 50

C 100

D 500

M 1000

这里,我们只介绍一下 1000 以内的数字的表示法。

单个符号重复多少次,就表示多少倍。最多重复 3 次。比如:CCC 表示 300,XX 表示 20,但 150 并不用 LLL 表示,这个规则仅适用于 I X C M。

如果相邻级别的大单位在右,小单位在左,表示大单位中扣除小单位。比如:IX 表示 9,IV 表示 4, XL 表示 40 更多的输入描述参见下表,你找到规律了吗?

I,1

II,2

III,3

IV,4

V,5

VI,6

VII,7

VIII,8

IX,9

X,10

XI,11

XII,12

XIII,13

XIV,14

XV,15

XVI,16

XVII,17

XVIII,18

XIX,19

XX,20

XXI,21

XXII,22

XXIX,29

XXX,30

XXXIV,34

XXXV,35

XXXIX,39

XL,40

L,50

LI,51

LV,55

LX,60

LXV,65

LXXX,80

XC,90

XCIII,93

XCV,95

XCVIII,98

XCIX,99

C,100

CC,200

CCC,300

CD,400

D,500

DC,600

DCC,700

DCCC,800

CM,900

CMXCIX,999

本题目的要求是:请编写程序,由用户输入若干个罗马数字串,程序输出对应的十进制表示。

输入描述

第一行是整数 n\ (n<100)n (n<100) ,表示接下来有 nn 个罗马数字。

以后每行一个罗马数字。罗马数字大小不超过 999。

输出描述

要求程序输出 nn 行,就是罗马数字对应的十进制数据。

输入输出样例

示例

输入

3
LXXX
XCIII
DCCII

输出

80
93
702

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M
#include<bits/stdc++.h>
using namespace std;

string mon = "IVXLCDM";

int number[] = {1,5,10,50,100,500,1000}; 

int main(){
	int count,sum;
	cin>>count;
	while(count--){
		sum = 0;	//记录总数 
		string str;
		cin>>str;
		for(int i=0;i<str.size()-1;i++){
			sum +=mon.find(str[i])>=mon.find(str[i+1])?number[mon.find(str[i])]:-number[mon.find(str[i])];    //将当前字符与下一个字符相比,如果位置靠前,则需要减去当前字符的数值
		}
		sum+=number[mon.find(str[str.size()-1])];
		cout<<sum<<endl;
	}
	
} 

删除字符

https://www.lanqiao.cn/problems/544/learning/

题目描述

给定一个单词,请问在单词中删除 tt 个字母后,能得到的字典序最小的单词是什么?

输入描述

输入的第一行包含一个单词,由大写英文字母组成。

第二行包含一个正整数 tt。

其中,单词长度不超过 100100,tt 小于单词长度。

输出描述

输出一个单词,表示答案。

输入输出样例

示例 1

输入

LANQIAO
3

输出

AIAO

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M

刚拿到这道题,我还想复杂了,以为是求最长递增子序列,考虑用动态规划。

其实这个代码并不严谨,因为并没有找到最长的字典序,如果选中第一个字符作为字典序所能产生的最长字典序长度为3,但是不选中第一个字符整个字符串的最长字典序可能长度不仅仅是三,所以需要根据题意来选择是否使用动态规划。

在这道题中并不需要你去判断长度问题,只是一个练习字符串的基础题。

#include<bits/stdc++.h>
using namespace std;

int main(){
	string str;
	cin>>str;		//输入字符串 
	int number,i;
	cin>>number; 	//记录删除的单词个数 
	string clo;
	int temp;		//记录上一个字符的大小 
	for(i=0;i<str.size();i++){
		if(number&&str[i]>temp){
			number--;
		}else{
			clo.append(str.substr(i,1));
		}
		temp = str[i];
	}
	cout<<clo;
} 

扫雷游戏

https://www.lanqiao.cn/problems/358/learning/

题目描述

扫雷游戏是一款十分经典的单机小游戏。在 nn 行 mm 列的雷区中有一些格子含有地雷(称之为地雷格),其他格子不含地雷(称之为非地雷格)。玩家翻开一个非地雷格时,该格将会出现一个数字------提示周围格子中有多少个是地雷格。游戏的目标是在不翻出任何地雷格的条件下,找出所有的非地雷格。

现在给出 nn 行 mm 列的雷区中的地雷分布,要求计算出每个非地雷格周围的地雷格数。

注:一个格子的周围格子包括其上、下、左、右、左上、右上、左下、右下八个方向上与之直接相邻的格子。

输入描述

输入的第一行是用一个空格隔开的两个整数 nn 和 mm,分别表示雷区的行数和列数。

接下来 nn 行,每行 mm 个字符,描述了雷区中的地雷分布情况。字符'*'表示相应格子是地雷格,字符'?'表示相应格子是非地雷格。相邻字符之间无分隔符。

其中,1 \leq n \leq 100,1 \leq m \leq 1001≤n≤100,1≤m≤100。

输出描述

输出包含 nn 行,每行 mm 个字符,描述整个雷区。用'*'表示地雷格,用周围的地雷个数表示非地雷格。相邻字符之间无分隔符。

输入输出样例

示例 1

输入

3 3
*??
???
?*?

输出

*10
221
1*1

示例 2

输入

2 3
?*?
*??

输出

2*1
*21

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M
#include<bits/stdc++.h>
using namespace std;
 
int a[8][2] = {{-1,-1},{0,-1},{1,-1},{-1,0},{1,0},{-1,1},{0,1},{1,1}};
 
int main(){
	int n,m;
	cin>>n>>m;
	int d[n][m];
	for(int i=0;i<n;i++){	//录入扫雷区域 
	for(int j=0;j<m;j++){
		char c ;
		cin>>c;
		 if(c=='1'){
			d[i][j] = -1;
		}else {
			d[i][j] = 0;
		}
	}
	}
		
	for(int i=0;i<n;i++){
	for(int j=0;j<m;j++){
		if(d[i][j]==-1){
			cout<<'9';
		} else{
			for(int z =0;z<8;z++){
				int x,y;
				x = i+a[z][0];
				y = j+a[z][1];
				if((x>-1)&&(x<n)&&(y>-1)&&(y<m)&&(d[x][y]==-1))
				d[i][j]++;
			}
			cout<<d[i][j];
		}
		if(j<m-1)
		cout<<" ";
	}
	cout<<endl;
	}
} 

潜伏者

https://www.lanqiao.cn/problems/519/learning

题目描述

R 国和 S 国正陷入战火之中,双方都互派间谍,潜入对方内部,伺机行动。

历尽艰险后,潜伏于 S 国的 R 国间谍小 C 终于摸清了 S 国军用密码的编码规则:

  1. S 国军方内部欲发送的原信息经过加密后在网络上发送,原信息的内容与加密后所得的内容均由大写字母 ‘A’-‘Z’构成(无空格等其他字符)。

  2. S 国对于每个字母规定了对应的“密字”。加密的过程就是将原信息中的所有字母替换为其对应的“密字”。

  3. 每个字母只对应一个唯一的“密字”,不同的字母对应不同的“密字”。“密字”可以和原字母相同。

例如,若规定‘A’的密字为‘A’,‘B’ 的密字为 ‘C’(其他字母及密字略),则原信息“ABA”被加密为“ACA”。

现在,小 C 通过内线掌握了 S 国网络上发送的一条加密信息及其对应的原信息。小 C希望能通过这条信息,破译 S 国的军用密码。小 C 的破译过程是这样的:扫描原信息,对于原信息中的字母 xx(代表任一大写字母),找到其在加密信息中的对应大写字母 yy,并认为在密码里 yy 是 xx 的密字。如此进行下去直到停止于如下的某个状态:

  1. 所有信息扫描完毕,‘A’-‘Z’ 所有 26 个字母在原信息中均出现过并获得了相应的“密字”。

  2. 所有信息扫描完毕,但发现存在某个(或某些)字母在原信息中没有出现。

  3. 扫描中发现掌握的信息里有明显的自相矛盾或错误(违反 S 国密码的编码规则)。例如某条信息“XYZ”被翻译为“ABA”就违反了“不同字母对应不同密字”的规则。

在小 C 忙得头昏脑涨之际,R 国司令部又发来电报,要求他翻译另外一条从 S 国刚刚截取到的加密信息。现在请你帮助小 C:通过内线掌握的信息,尝试破译密码。然后利用破译的密码,翻译电报中的加密信息。

输入描述

输入共 3 行,每行为一个长度在 1 到 100 之间的字符串。

第 1 行为小 C 掌握的一条加密信息。

第 2 行为第 1 行的加密信息所对应的原信息。

第 3 行为 R 国司令部要求小 C 翻译的加密信息。

输入数据保证所有字符串仅由大写字母‘A’-‘Z’构成,且第 1 行长度与第 2 行相等。

输出描述

输出 1 行。

若破译密码停止时出现 2,3 两种情况,请你输出 Failed(注意首字母大写,其它小写)。否则请输出利用密码翻译电报中加密信息后得到的原信息。

输入输出样例

示例 1

输入

AA
AB
EOWIE   

输出

Failed 

示例 2

输入

QWERTYUIOPLKJHGFDSAZXCVBN
ABCDEFGHIJKLMNOPQRSTUVWXY
DSLIEWO

输出

Failed 

示例 3

输入

MSRTZCJKPFLQYVAWBINXUEDGHOOILSMIJFRCOPPQCEUNYDUMPP
YIZSDWAHLNOVFUCERKJXQMGTBPPKOIYKANZWPLLVWMQJFGQYLL
FLSO

输出

NOIP 

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M
#include <iostream>
using namespace std;
int pwd[27];
bool s[27], t[27];
int main()
{
  string m, y, v;
  cin >> m >> y >> v;
  int num = 0;
  for(int i = 0; i < m.size(); ++i) {
    if(!s[m[i] - 'A'] && !t[y[i] - 'A']) {
      pwd[m[i] - 'A'] = y[i];
      s[m[i] - 'A'] = t[y[i] - 'A'] = true;
      num++;
    } else if(pwd[m[i] - 'A'] != y[i]) {
      cout << "Failed";
      return 0;
    }
  }
  if(num != 26) {
    cout << "Failed";
    return 0;
  }
  for(int i = 0; i < v.size(); ++i) {
    printf("%c", pwd[v[i] - 'A']);
  }
  return 0;
}

ISBN 号码

https://www.lanqiao.cn/problems/523/learning/

题目描述

每一本正式出版的图书都有一个 ISBN 号码与之对应,ISBN 码包括 9 位数字、1 位识别码和 3 位分隔符,其规定格式如 “x-xxx-xxxxx-x”,其中符号“-”是分隔符(键盘上的减号),最后一位是识别码,例如0-670-82162-4 就是一个标准的 ISBN 码。ISBN 码的首位数字表示书籍的出版语言,例如 0 代表英语;第一个分隔符“-”之后的三位数字代表出版社,例如 670 代表维京出版社;第二个分隔之后的五位数字代表该书在出版社的编号;最后一位为识别码。

识别码的计算方法如下:

首位数字乘以 1 加上次位数字乘以 2 …… 以此类推,用所得的结果 mod 11,所得的余数即为识别码,如果余数为 10,则识别码为大写字母 X。例如 ISBN 号码 0-670-82162-4 中的识别码 4 是这样得到的:对 067082162这9 个数字,从左至右,分别乘以 1,2,…,9,再求和,即 0×1+6×2+……+2×9=158,然后取 158 mod 11 的结果 4 作为识别码。 你的任务是编写程序判断输入的ISBN号码中识别码是否正确,如果正确,则仅输出 Right;如果错误,则输出你认为是正确的 ISBN 号码。

输入描述

输入一行,是一个字符序列,表示一本书的 ISBN 号码(保证输入符合 ISBN 号码的格式要求)。

输出描述

输出一行,假如输入的 ISBN 号码的识别码正确,那么输出Right,否则,按照规定的格式,输出正确的 ISBN 号码(包括分隔符“-”)。

输入输出样例

示例 1

输入

0-670-82162-4

输出

Right

示例 2

输入

0-670-82162-0

输出

0-670-82162-4 

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M
#include<bits/stdc++.h>
using namespace std;
int step[10],k=0,t=1,sum;
int main(){
    string s;
    cin>>s;
    for(int i=0;i<s.length();i++)
    if(s[i]!='-'){
     step[k++]=s[i]-'0';
    // cout<<step[k-1];
    }  
for(int i=0;i<k-1;i++)
  { sum+=step[i]*t;
           ++t;
}    
  int ans=sum%11;
    if(ans==step[k-1]||ans+30==step[k-1])
    cout<<"Right";
    else{
     if(ans==10){
        for(int i=0;i<s.length();i++){
         if(i==s.length()-1)cout<<'X';
         else cout<<s[i];}
        } 
    if(ans!=10){
            for(int i=0;i<s.length();i++){
         if(i==s.length()-1)cout<<ans;
         else cout<<s[i];}
    }
}
    return 0;
}

字符串的展开

https://www.lanqiao.cn/problems/536/learning/

题目描述

在初赛普及组的 "阅读程序写结果" 的问题中,我们曾给出一个字符串展开的例子:如果在输入的字符串中,含有类似于 d-h 或 4-8 的子串,我们就把它当作一种简写,输出时,用连续递增的字母或数字串替代其中的减号,即,将上面两个子串分别输出为 defgh 和 45678 。在本题中,我们通过增加一些参数的设置,使字符串的展开更为灵活。具体约定如下:

(1)遇到下面的情况需要做字符串的展开:在输入的字符串中,出现了减号 - ,减号两侧同为小写字母或同为数字,且按照 ASCII 码的顺序,减号右边的字符严格大于左边的字符。

(2)参数 p1p1 :展开方式。 p1=1p1=1时,对于字母子串,填充小写字母; p1=2p1=2 时,对于字母子串,填充大写字母。这两种情况下数字子串的填充方式相同。 p1=3p1=3 时,不论是字母子串还是数字子串,都用与要填充的字母个数相同的星号 * 来填充。

(3)参数 p2p2 :填充字符的重复个数。 p2=kp2=k 表示同一个字符要连续填充 kk 个。例如,当 p2=3p2=3 时,子串 d-h 应扩展为 deeefffgggh 。减号两侧的字符不变。

(4)参数 p3p3 :是否改为逆序: p3=1p3=1 表示维持原有顺序, p3=2p3=2 表示采用逆序输出,注意这时仍然不包括减号两端的字符。例如当 p1=1、 p2=2、 p3=2p1=1、p2=2、p3=2 时,子串 d-h 应扩展为 dggffeeh 。

(5)如果减号右边的字符恰好是左边字符的后继,只删除中间的减号,例如: d-e 应输出为 de , 3-4 应输出为 34 。如果减号右边的字符按照ASCII码的顺序小于或等于左边字符,输出时,要保留中间的减号,例如: d-d 应输出为 d-d , 3-1 应输出为 3-1 。

输入描述

第 1 行为用空格隔开的 3 个正整数,依次表示参数 p1p1 , p2p2 , p3p3 。

第 2 行为一行字符串,仅由数字、小写字母和减号 - 组成。行首和行末均无空格。

其中,1 \leq p1 \leq 3, 1 \leq p2 \leq 8, 1 \leq p3 \leq 21≤p1≤3,1≤p2≤8,1≤p3≤2。字符串长度不超过 100100。

输出描述

输出一行,为展开后的字符串。

输入输出样例

示例 1

输入

1 2 1
abcs-w1234-9s-4zz

输出

abcsttuuvvw1234556677889s-4zz

示例 2

输入

2 3 2
a-d-d

输出

aCCCBBBd-d

示例 3

输入

3 4 2
di-jkstra2-6

输出

dijkstra2************6

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M

#include<bits/stdc++.h> 
using namespace std;
int p1,p2,p3;

bool lower(char a,char b){
	if((a>='a'&&a<='z')&&(b>='a'&&b<='z'))
	return true;
	return false;
}

bool supper(char a,char b ){
	if((a>='A'&&a<='Z')&&(b>='A'&&b<='Z'))
	return true;
	return false;
}

bool digit(char a,char b ){
	if((a>='0'&&a<='9')&&(b>='0'&&b<='9'))
	return true;
	return false;
}

void lower_c(char a,char b){	//处理两个都为小写字母时 
	char c;
	if(a>=b){
		cout<<"-";
	}else{
		int su = b-a;
		int i = (p3==1)?1:su-1;	//初始化i的值 
		int step = (p3==1)?1:-1;	//判断顺序还是逆序 
		while(i>0&&i<su) {
			for(int j=0;j<p2;j++){
				if(p1==1) {
					c = a+i;
					cout<<c;
				}else if(p1==2){
					c=a-'a'+'A'+i;
					cout<<c;	//将小写字母转化成大写字母 
				}else{
					cout<<'*'; 
				} 
			}
			i+=step;		 
		}
	}
}

void supper_c(char a,char b){	//处理两个都为大写字母时 
	char c;
	if(a>=b){
		cout<<"-";
	}else{
		int su = b-a;
		int i = (p3==1)?1:su-1;	//初始化i的值 
		int step = (p3==1)?1:-1;	//判断顺序还是逆序 
		while(i>0&&i<su) {
			for(int j=0;j<p2;j++){
				if(p1==1) {
					c=a-'A'+'a'+i;	//将大写字母转化成小写字母 
					cout<<c;
				}else if(p1==2){
					c=a+i;
					cout<<c;	 
				}else{
					cout<<'*'; 
				} 
			}
			i+=step;		 
		}
	}
}

void  digit_c(char a,char b){	//处理两个都为数字时 
	char c;
	if(a>=b){
		cout<<"-";
	}else{
		int su = b-a;
		int i = (p3==1)?1:su-1;	//初始化i的值 
		int step = (p3==1)?1:-1;	//判断顺序还是逆序 
		while(i>0&&i<su) {
			for(int j=0;j<p2;j++){
				if(p1==3) {
					cout<<'*'; 
				}else {
					c =a+i;
					cout<<c;	//输出数字 
				}
			}
			i+=step;		 
		}
	}
} 



int main(){

	cin>>p1>>p2>>p3;
	string str;
	cin>>str;
	cout<<str[0];
	for(int i=1;i<str.size()-1;i++){
		if(str[i]=='-'){		//如果当前符号为- 则需要判断是否需要转义 
			if(lower(str[i-1],str[i+1])){	//c++给我们提供了直接判断小写字母的函数islower() 
				lower_c(str[i-1],str[i+1]) ;
			}else if(supper(str[i-1],str[i+1])){	//c++给我们提供了直接判断大写字母的函数isupper()
				supper_c(str[i-1],str[i+1]) ;
			}else if(digit(str[i-1],str[i+1])){	//c++给我们提供了直接判断数字的函数isdigit()
				digit_c(str[i-1],str[i+1]) ;
			}else{
				cout<<str[i]; 
			} 
		}else{
			cout<<str[i];
		}
	}
	cout<<str[str.size()-1];
}

FBI树

https://www.lanqiao.cn/problems/571/learning/

题目描述

我们可以把由 “0” 和 “1” 组成的字符串分为三类:全 “0” 串称为 B 串,全 “1” 串称为 I 串,既含 “0” 又含 “1” 的串则称为 F 串。

FBI树是一种二叉树,它的结点类型也包括 F 结点,B 结点和 I 结点三种。由一个长度为 2^N2N 的 “01” 串 S 可以构造出一棵 FBI 树 T,递归的构造方法如下:

  1. T 的根结点为 R,其类型与串 S 的类型相同;

  2. 若串 S 的长度大于 1,将串 S 从中间分开,分为等长的左右子串 S1 和 S2 ;由左子串 S1 构造 R 的左子树 T1,由右子串 S2 构造 R 的右子树 T2。

现在给定一个长度为 2^N2N 的 “01” 串,请用上述构造方法构造出一棵FBI树,并输出它的后序遍历序列。

输入描述

第一行是一个整数 N(0 \leq N \leq 10)N(0≤N≤10)。

第二行是一个长度为 2^N2N 的 “01” 串。

输出描述

输出一个字符串,即 FBI 树的后序遍历序列。

输入输出样例

示例 1

输入

3
10001011

输出

IBFBBBFIBFIIIFF

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M
#include<bits/stdc++.h>
using namespace std;
string s;

void FBI(string s,int len){
	if(s.size()>1){
		FBI(s.substr(0,len/2),len/2);
		FBI(s.substr(len/2,len/2),len/2);
	}
	if(s == string(len,'0')) cout<<'B';
	else if(s == string(len,'1')) cout<<'I';
	else cout<<'F'; 
} 

int main(){
	int n;
	cin>>n>>s;
	FBI(s,s.size());
} 

  • 1
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狗头实习生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值