算法题总结
1.7基础编程之字符串
05:输出亲朋字符串
描述:编写程序,求给定字符串s的亲朋字符串s1。
亲朋字符串s1定义如下:给定字符串s的第一个字符的ASCII值加第二个字符的ASCII值,得到第一个亲朋字符; 给定字符串s的第二个字符的ASCII值加第三个字符的ASCII值,得到第二个亲朋字符;依此类推,直到给定字符串s的倒数第二个字符。亲朋字符串的最 后一个字符由给定字符串s的最后一个字符ASCII值加s的第一个字符的ASCII值。
输入:
输入一行,一个长度大于等于2,小于等于100的字符串。字符串中每个字符的ASCII值不大于63。
输出:
输出一行,为变换后的亲朋字符串。输入保证变换后的字符串只有一行。
样例输入:1234
样例输出:cege
#include<iostream>
#include<string>
using namespace std;
int main()
{
string a;
getline(cin,a);
for(int i=0;i<a.length()-1;i++) //这里只处理前几个字符,最后一个字符在这里不做处理
{
cout<<char(a[i]+a[i+1]);
}
cout<<char(a[a.length()-1]+a[0]);
return 0;
}
这个题比较简单,一个for循环实现循环加法,最后一个字符和第一个字符相加进行强制类型转换,最后再生成一个新的ASCI码。
06:合法C标识符
描述:给定一个不包含空白符的字符串,请判断是否是C语言合法的标识符号(注:题目保证这些字符串一定不是C语言的保留字)。
C语言标识符要求:
1、非保留字
2、只包含字母、数字及下划线(“_”)
3、不以数字开头。
输入:一行,包含一个字符串,字符串中不包含任何空白字符,且长度不大于20。
输出:一行,如果它是c语言的合法标识符,则输出yes,否则输出no
样例输入:RKPEGX9R;TWyYcp
样例输出:no
#include<iostream>
#include<string>
using namespace std;
int main()
{
string a;
cin>>a;
if(a[0]>='0'&&a[0]<='9')
{
cout<<"no";
return 0;
}
for(int i=0;i<a.length();i++)
{
if(a[i]>='0'&&a[i]<='9')
continue;
if(a[i]>='a'&&a[i]<='z')
continue;
if(a[i]>='A'&&a[i]<='Z')
continue;
if(a[i]=='_')
continue;
cout<<"no";
return 0;
}
cout<<"yes";
return 0;
}
总结:这个题也比较简单,写一个for循环,我刚开始的思路是用if语句去判断不能作为它这个标识符的词,后来看见视频,我觉得自己的思维太古板了,这个题他说的是不能作为标识符的单词有哪些,其实你可以转换成什么样的词它可以是???还是自己的思维太古板了。
07:配对碱基链
这个题比较简单,就不总结了,直接就是一个for循环,if语句进行判断是否是对应的碱基链。
08:字符替换
描述:把一个字符串中特定的字符全部用给定的字符进行替换,得到一个新的字符串。
输入:只有一行,由一个字符串和两个字符组成,中间用单个空格隔开。字符串是待替换的字符串,字符串长度小于等于30个字符,且不含空格等空白符;
接下来一个字符为需要被替换的特定字符;
接下来一个字符为用于替换的给定字符。
输出:一行,即替换后的字符串
样例输入:hello-how-are-you o O
样例输出:hellO-hOw-are-yOu
#include<iostream>
#include<string>
using namespace std;
int main()
{
string a;
char b,c;
cin>>a>>b>>c;
for(int i=0;i<a.length();i++)
{
if(a[i]==b)
a[i]=c;
}
cout<<a;
}
09:密码翻译
描述:在情报传递过程中,为了防止情报被截获,往往需要对情报用一定的方式加密,简单的加密算法虽然不足以完全避免情报被破译,但仍然能防止情报被轻易的识别。我们给出一种最简的的加密方法,对给定的一个字符串,把其中从a-y,A-Y的字母用其后继字母替代,把z和Z用a和A替代,其他非字母字符不变,则可得到一个简单的加密字符串。
输入:输入一行,包含一个字符串,长度小于80个字符。
输出:输出每行字符串的加密字符串。
样例输入:Hello! How are you!
样例输出:Ifmmp! Ipx bsf zpv!
#include<iostream>
#include<string>
using namespace std;
int main()
{
string a;
getline(cin,a);
for(int i=0;i<a.length();i++)
{
if(a[i]>='a'&&a[i]<='y'||a[i]>='A'&&a[i]<='Y')
{
cout<<char(a[i]+1);
}
if(a[i]=='z')
{
cout<<'a';
}
if(a[i]=='Z')
{
cout<<'A';
}
if(a[i]<'A'||a[i]>'Z'&&a[i]<'a'||a[i]>'z')
{
cout<<a[i];//这里是判断其他字符,比如:!、空格等的字符
}
}
return 0;
}
####### 总结:这个题也比较简单,就是要看清楚题意,它是在a-y之间进行判断,不是a-z,并且在这个题里面,字符与它下一个字符之间其实就差了1,这个在程序设计时,知道就行了。
10:简单密码
描述:Julius Caesar曾经使用过一种很简单的密码。对于明文中的每个字符,将它用它字母表中后5位对应的字符来代替,这样就得到了密文。比如字符A用F来代替。如下是密文和明文中字符的对应关系。
密文
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
明文
V W X Y Z A B C D E F G H I J K L M N O P Q R S T U
你的任务是对给定的密文进行解密得到明文。
你需要注意的是,密文中出现的字母都是大写字母。密文中也包括非字母的字符,对这些字符不用进行解码。
输入:一行,给出密文,密文不为空,而且其中的字符数不超过200。
输出:输出一行,即密文对应的明文。
样例输入:NS BFW, JAJSYX TK NRUTWYFSHJ FWJ YMJ WJXZQY TK YWNANFQ HFZXJX
样例输出:IN WAR, EVENTS OF IMPORTANCE ARE THE RESULT OF TRIVIAL CAUSES
#include<iostream>nclude<iostream>
#include<string>nclude<string>
using namespace std;ing namespace std;
int main() {t main()
string a;
getline(cin,a); string a;
for(int i=0; i<a.length(); i++) { getline(cin,a);
if(a[i]>='A'&&a[i]<='E') { for(int i=0;i<a.length();i++)
cout<<char(a[i]-5+26);//就这行代码需要注意,因为它减5以后,就会变成其他很奇怪的字符 {
} else if(a[i]>='F'&&a[i]<='Z') if(a[i]>='A'&&a[i]<='E')
cout<<char(a[i]-5); {
else cout<<char(a[i]-5+26);
cout<<a[i];}
} else if(a[i]>='F'&&a[i]<='Z')
return 0; cout<<char(a[i]-5);
} else
cout<<a[i];
}
return 0;
总结:这个题就是在cout<<char(a[i]-5+26);这行代码这里有点绕,因为它给出的是密文,你现在要变成明文,就需要减5,但是字符A-E减5以后,它就会变成其他类型的字符,不属于26个英文字母了,所以在这里面减5以后,你依旧需要再加26,把它变回26个英文字母里面的字符。
12:加密的病历单
描述:小英是药学专业大三的学生,暑假期间获得了去医院药房实习的机会。
在药房实习期间,小英扎实的专业基础获得了医生的一致好评,得知小英在计算概论中取得过好成绩后,主任又额外交给她一项任务,解密抗战时期被加密过的一些伤员的名单。
经过研究,小英发现了如下加密规律(括号中是一个“原文 -> 密文”的例子)
1. 原文中所有的字符都在字母表中被循环左移了三个位置(dec -> abz)
2. 逆序存储(abcd -> dcba )
3. 大小写反转(abXY -> ABxy)
输入:一个加密的字符串。(长度小于50且只包含大小写字母)
输出:输出解密后的字符串。
样例输入:GSOOWFASOq
样例输出:Trvdizrrvj
#include<iostream>
#include<string>
using namespace std;
int main() {
string a;
getline(cin,a);
//向右走3位
for(int i=0; i<a.length(); i++) {
if(a[i]>='A'&&a[i]<='W'||a[i]>='a'&&a[i]<='w') {
a[i]=a[i]+3;
} else if(a[i]=='X')
a[i]='A';
else if(a[i]=='Y')
a[i]='B';
else if(a[i]=='Z')
a[i]='C';
else if(a[i]=='x')
a[i]='a';
else if(a[i]=='y')
a[i]='b';
else if(a[i]=='z')
a[i]='c';
}
//变换大小写
for(int i=0; i<a.length(); i++) {
if(a[i]>='A'&&a[i]<='Z') { //大写字母
a[i]=a[i]+32;
} else if(a[i]>='a'&&a[i]<='z') { //小写字母
a[i]=a[i]-32;
}
}
//逆序输出
for(int i=a.length()-1; i>=0; i--)
cout<<a[i];
}
总结:在这个题里面,我用的自己的方法去做的,但是这个题我犯了一个错误,就是在这个题里面,一定注意else if和if语句的使用,因为自己理解错误,导致这个题走了很多弯路,这个题的逻辑,我用的自己的逻辑实现没有看嘉持老师的视频,所以算是圆满完成这个题。
15:整理药名
描述:医生在书写药品名的时候经常不注意大小写,格式比较混乱。现要求你写一个程序将医生书写混乱的药品名整理成统一规范的格式,即药品名的第一个字符如果是字母要大写,其他字母小写。如将ASPIRIN、aspirin整理成Aspirin。
输入:第一行一个数字n,表示有n个药品名要整理,n不超过100。接下来n行,每行一个单词,长度不超过20,表示医生手书的药品名。药品名由字母、数字和-组成。
输出:n行,每行一个单词,对应输入的药品名的规范写法。
样例输入:
4
AspiRin
cisapride
2-PENICILLIN
Cefradine-6
这段代码是自己写的,但是在openjudge过不了,我在dev试了好几次,还是过不了
#include<iostream>
#include<string>
using namespace std;
int main() {
int n;
string a;
cin>>n;
// getline(cin,a);
for(int i=1; i<=n; i++) {
cin>>a;
if(a[0]>='A'&&a[0]<='Z') {
for(int j=1; j<a.length(); j++) {
if(a[j]>='A'&&a[j]<='Z')
a[j]=a[j]+32;
}
// cout<<a<<"\n";
} else if(a[0]>='a'&&a[0]<='z') {
a[0]=a[0]-32;
for(int j=1; j<a.length(); j++) {
if(a[j]>='A'&&a[j]<='Z')
a[j]=a[j]+32;
}
// cout<<a<<"\n";
} else if(a[0]>'0'&&a[0]<'9') {
for(int j=1; j<a.length(); j++) {
if(a[j]>='A'&&a[j]<='Z') {
a[j]=a[j]+32;
}
}
// cout<<a<<"\n";
}
cout<<a<<endl;
}
}
底下这段代码是我在博客上面找的一段代码,我自己在dev跑了一遍,发现和我的代码结果一样,但是它在openjudge上面竟然过了,不知道为什么。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
int n;
cin >> n;
while(n--)
{
cin >> s;
if(s[0]>='a' && s[0]<='z')
s[0]-=32;
for(int i=1;i<s.size();i++)
{
if(s[i]>='A' && s[i]<='Z')
s[i]+=32;
}
cout << s << endl;
}
return 0;
}
这个题我自己写的时候,用的方法可能比较笨,也比较传统,我自己觉得代码是没有问题的,逻辑什么的也都是对的,不知道就是为啥过不了
16:忽略字符串大小写的比较
描述:一般我们用strcmp可比较两个字符串的大小,比较方法为对两个字符串从前往后逐个字符相比较(按ASCII码值大小比较),直到出现不同的字符或遇到’\0’为止。如果全部字符都相同,则认为相同;如果出现不相同的字符,则以第一个不相同的字符的比较结果为准(注意:如果某个字符串遇到’\0’而另一个字符串还未遇到’\0’,则前者小于后者)。但在有些时候,我们比较字符串的大小时,希望忽略字母的大小,例如"Hello"和"hello"在忽略字母大小写时是相等的。请写一个程序,实现对两个字符串进行忽略字母大小写的大小比较。
输入:输入为两行,每行一个字符串,共两个字符串。(每个字符串长度都小于80)
输出:如果第一个字符串比第二个字符串小,输出一个字符"<";
如果第一个字符串比第二个字符串大,输出一个字符">";
如果两个字符串相等,输出一个字符"="。
样例输入:
Hello, how are you?
hello, How are you?
样例输出:
=
以下是我自己编写的代码,在dev上面运行完全正确,可是openjudge不通过
#include<iostream>
#include<string>
using namespace std;
int main() {
string a,b;
int i;
getline(cin,a);
getline(cin,b);
int alen=a.length();
int blen=b.length();
if(alen>blen) { //如果b<a,当前面的字符都相同时,则a>b
// cout<<"a的长度大于b"<<"\n";
for( i=0; i<blen; i++) {
if(a[i]==b[i]||a[i]==(b[i]+32)||a[i]==(b[i]-32))
continue;
else if(a[i]<b[i]) {
cout<<"<"<<endl;
break;
} else if(a[i]>b[i]) {
cout<<">"<<endl;
break;
}
}
if(i==blen)
cout<<">";
}
if(alen<blen) { //如果b>a,当前面的字符都相同时,则a<b
// cout<<"a的长度小于b"<<"\n";
for( i=0; i<alen; i++) {
if(a[i]==b[i]||a[i]==(b[i]+32)||a[i]==(b[i]-32))
continue;
else if(a[i]<b[i]) {
cout<<"<";
break;
}
else if(a[i]>b[i]) {
cout<<">";
break;
}
}
if(i==alen)
cout<<"<";
}
if(alen==blen) {
for( i=0; i<alen; i++) {
if(a[i]==b[i]||a[i]==(b[i]+32)||a[i]==(b[i]-32))
continue;
if(a[i]>b[i]) {
cout<<">";
break;
} else if(a[i]<b[i]) {
cout<<"<";
break;
}
}
if(i==alen)
cout<<"=";
}
}
以下是嘉持老师的代码,能通过openjudge,方法更简单,不过我还是觉得我的思路没有问题
#include<bits/stdc++.h>
using namespace std;
int main()
{
string a;
string b;
getline(cin,a);
getline(cin,b);
int x=a.size();
int d=b.size();
for(int i=0;i<=x-1;i++)
{
if(a[i]>='a'&&a[i]<='z')
{
a[i]=a[i]-32;
}
}
for(int i=0;i<=d-1;i++)
{
if(b[i]>='a'&&b[i]<='z')
{
b[i]=b[i]-32;
}
}
if(a<b)
{
cout<<"<";
}
else if(a>b)
{
cout<<">";
}
else
{
cout<<"=";
}
return 0;
}
17:字符串判等
描述:判断两个由大小写字母和空格组成的字符串在忽略大小写,且忽略空格后是否相等。
输入:两行,每行包含一个字符串。
输出:若两个字符串相等,输出YES,否则输出NO。
若两个字符串相等,输出YES,否则输出NO。
样例输入:
a A bb BB ccc CCC
Aa BBbb CCCccc
样例输出:
YES
#include<iostream>
#include<string>
using namespace std;
int main() {
string a,b,c,d;
getline(cin,a);
getline(cin,b);
c="";
d="";
for(int i=0; i<a.length(); i++) {
if(a[i]>='A'&&a[i]<='Z') {
a[i]=a[i]+32;
}
}
for(int i=0; i<b.length(); i++) {
if(b[i]>='A'&&b[i]<='Z') {
b[i]=b[i]+32;
}
}
for(int i=0; i<a.length(); i++) {
if(a[i]>='a'&&a[i]<='z') {
c=c+a[i];
}
}
for(int i=0; i<b.length(); i++) {
if(b[i]>='a'&&b[i]<='z') {
d=d+b[i];
}
}
if(c==d)
cout<<"YES";
else
cout<<"NO";
}
总结:这个题是它把一行字符串里面的所有字符按照小写字母转换,然后把它放在一个字符串里面,去掉空格然后纯字母进行比较,跟刚才那个题一样,string应该是可以直接比较,不用设置什么for循环再挨个进行比较,最后把同时字母的两行字符串进行比较,判断是否相同。
18:验证字串
描述:输入两个字符串,验证其中一个串是否为另一个串的子串。
输入:输入两个字符串, 每个字符串占一行,长度不超过200且不含空格。
输出:若第一个串s1是第二个串s2的子串,则输出(s1) is substring of (s2)。否则,若第二个串s2是第一个串s1的子串,输出(s2) is substring of (s1)。否则,输出 No substring
编译器完全正确,还是过不了openjudge,很奔溃,
#include<iostream>
#include<string>
using namespace std;
int main() {
string a,b,c;
int count=0;
getline(cin,a);
getline(cin,b);
if(a.length()>b.length()) { //那就是b是a的字串判断是否有可能
int j=0;
for(int i=0; i<a.length(); i++) {
if(a[i]==b[j]) {
j++;
count++;
}
}
if(count>1) {
cout<<b<<" is substring of "<<a;
} else
cout<<"No substring";
}
if(a.length()<b.length()) {
int j=0;
for(int i=0; i<b.length(); i++) {
if(b[i]==a[j]) {
j++;
count++;
}
}
if(count>1) {
cout<<a<<" is substring of "<<b;
} else
cout<<"No substring";
}
if(a.length()==b.length()) {
int j=0;
for(int i=0; i<b.length(); i++) {
if(b[i]==a[j]) {
j++;
count++;
}
}
if(count>1) {
cout<<a<<" is substring of "<<b;
} else
cout<<"No substring";
}
}
以下是嘉持老师给出的代码,我自己觉得逻辑应该都差不多
#include<iostream>
#include<string>
using namespace std;
int main()
{
string a,b,c;
getline(cin,a);
getline(cin,b);
for(int i=0;i<b.length();i++)
{
c="";
for(int j=0;j<a.length();j++)
{
c=c+b[j+i];
}
if(a==c)
{
cout<<a<<" is substring of "<<b;
return 0;
}
}
for(int i=0;i<a.length();i++)
{
c="";
for(int j=0;j<b.length();j++)
{
c=c+a[j+i];
}
if(b==c)
{
cout<<b<<" is substring of "<<a ;
return 0;
}
}
cout<<"No substring";
}
19:字符串移位包含问题
描述:对于一个字符串来说,定义一次循环移位操作为:将字符串的第一个字符移动到末尾形成新的字符串。给定两个字符串s1和s2,要求判定其中一个字符串是否是另一字符串通过若干次循环移位后的新字符串的子串。例如CDAA是由AABCD两次移位后产生的新串BCDAA的子串,而ABCD与ACBD则不能通过多次移位来得到其中一个字符串是新串的子串。
输入:一行,包含两个字符串,中间由单个空格隔开。字符串只包含字母和数字,长度不超过30。
输出:如果一个字符串是另一字符串通过若干次循环移位产生的新串的子串,则输出true,否则输出false。
样例输入:AABCD CDAA
样例输出:true
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
string a,b,c;
cin>>a>>b;
c=b+b;
if(c.find(a)!=string::npos&&a.length()<=b.length())
{
cout<<"true";
return 0;
}
c=a+a;
if(c.find(b)!=string::npos&&b.length()<=a.length())
{
cout<<"true";
return 0;
}
cout<<"false";
return 0;
}
总结:这个题难就难在,你怎么去思考,因为如果要单纯通过移位去寻找字符字串,很难找,它直接把一个字符串进行叠加,这样的话,就能直接在新的字符串里面去找有没有字符字串的可能,就这个思维,很重要,如果仅仅只是通过不断去循环字符串去寻找字符字串,这个方法就不太好做,有点困难。
20:删除单词后缀
描述:给定一个单词,如果该单词以er、ly或者ing后缀结尾, 则删除该后缀(题目保证删除后缀后的单词长度不为0), 否则不进行任何操作。
输入:输入一行,包含一个单词(单词中间没有空格,每个单词最大长度为32)。
输出:输出按照题目要求处理后的单词。
样例输入:referer
样例输出:refer
#include<iostream>
#include<string>
using namespace std;
int main() {
string a;
cin>>a;
int alen=a.length();
if(a[alen-1]=='r'&&a[alen-2]=='e'||a[alen-1]=='y'&&a[alen-2]=='l')
alen-=2;
if(a[alen-1]=='g'&&a[alen-2]=='n'&&a[alen-3]=='i')
alen-=3;
for(int i=0; i<alen; i++)
cout<<a[i];
return 0;
}
总结:这道题目,完全就是一个判断题,我刚开始用循环做,一个for循环加上去,发现多余删除了两个er,所以是直接用if语句判断来做就可以了。不用加for循环。
21:单词替换
描述:输入一个字符串,以回车结束(字符串长度<=100)。该字符串由若干个单词组成,单词之间用一个空格隔开,所有单词区分大小写。现需要将其中的某个单词替换成另一个单词,并输出替换之后的字符串。
输入:输入包括3行,第1行是包含多个单词的字符串 s;第2行是待替换的单词a(长度 <= 100);第3行是a将被替换的单词b(长度 <= 100).s, a, b 最前面和最后面都没有空格.
输出:输出只有 1 行,将s中所有单词a替换成b之后的字符串。
样例输入:
You want someone to help you
You
I
样例输出:I want someone to help you
#include<iostream>
#include<string>
using namespace std;
int main() {
string a,b,c,d;
getline(cin,a);
cin>>b>>c;
a=a+' ';
for(int i=0; i<a.length(); i++) {
d="";
while(a[i]!=' ') {
d=d+a[i];
i++;
}
if(d==b)
cout<<c;
else
cout<<d;
cout<<' ';
}
return 0;
}