C++中字符串题目小汇(比纯C简单)
声明:最近在看c++(在学校只学过一点c语言),一边看书,一边做题。这里给大家小结一下最近遇到的几个题目,感觉c++在对字符串的处理上比纯c更占优势,也让我感受到一波c++的强大
文章目录
注:因为题目信息不太好表述,故直接给出链接,点击蓝色字体“题目信息”即可看到相关问题
例题:只出现一次的字符
概述问题:给定一个小写字母串,判断其中出现且仅出现一次的字母,如果有,输出靠前的那一个(针对有多个满足条件的情况),如果没有,输出“no”。
输入样例:abceabcd
输出样例:e
思路 && 做法: 两层循环,外层循环用来向后遍历,内层循环用来从头查找
代码如下:
#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
int main(void)
{
string str;
getline(cin, str);//也可用cin读取, cin >> str;
for (int i = 0; str[i]; i ++)//从头遍历,扫描直到结束
{
int j = 0;
//while循环,从头查找匹配,条件有三,分为两类,用&&相连
//一类:1.字符串不为空 二类:2.匹配不上 或 3.匹配到自身
//如不满足以上两类条件就退出循环,此时有两种情况
while (str[j] && (str[i] != str[j] || i == j))
++ j;
//一种是:字符匹配上了且不是自身,那么str[j]不为空
//另一种是:字符一个都没有匹配上,那么str[j]为空
if (!str[j])//str[j]为空输出仅出现一次的结果
{
cout << str[i] << endl;
return 0;
}
}
//否则输出:no表示没有找到出现仅一次的字符
cout << "no" << endl;
return 0;
}
一:单词替换
概述问题:输入三行,第一行为字符串句子s,第二行为字符串单词a,第三行为将a替换成的单词b,a、b和s长度不超过100。
输入样例:
You want someone to help you
You
I
输出样例:
I want someone to help you
代码如下:
- 偏向于C语言风格的C++代码(自己的):
#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
int main(void)
{
//mstr为主串(句子)、substr为需要替代的子串(单词)
//rpstr为需要替代的子串(单词),即rpstr代替substr
string mstr, substr, rpstr;
getline(cin, mstr);
cin >> substr >> rpstr;
for (int i = 0; mstr[i]; )
{
//输出主串mstr与待取代串substr匹配不上的字符
if (mstr[i] != substr[0])
while (mstr[i] != ' ' && mstr[i])
putchar(mstr[i++]);//直到该单词结束,遇到空格或者'\0'(末尾)
else
{
int j = 0, k = i;//匹配上的字符先不输出,攒着,这时主串通过k来动,不影响i的值
while (mstr[k] == substr[j] && mstr[k] && substr[j])
++ k, ++ j;
if (j == substr.size() && (!mstr[k] || mstr[k] == ' '))//攒齐了后,将其替换成rpstr输出
{
cout << rpstr;
i += j;//输出rpstr,下标i需要增加,跳过原先substr的字符
}
else//未匹配上就输出一个字符
{
while (mstr[i] != ' ' && mstr[i])
putchar(mstr[i++]);
}
}
if (mstr[i] == ' ') putchar(' '), ++ i;
}
cout << endl;
return 0;
}
- 精炼成熟的C++语言代码(别人的):
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main(void)
{
string s, a, b;
getline(cin, s);
cin >> a >> b;
stringstream s_cin(s);//s_cin()为自定义输入流名称
//名称任意取,比如abcd(s),表示将s作为输入流
string str;
(s_cin >> str)
{
if (str == a) cout << b << ' ';
else cout << str << ' ';
}
return 0;
}
二:字符串中最长连续出现的字符
概述问题:求一个字符串中最长的连续出现的字符,输出该字符及其出现的次数,字符串中部无空白字符(空格、回车、tab),如果有两个以上长度都是最大,输出第一个。
输入样例:
2
aaaaabbbbbcccccccdddddddddd
abcdefghigk
输出样例:
d 10
a 1
思路 && 做法: 双指针,三层循环,第一层控制多次输入,第二层对于一次输入,第一指针i从头扫描遍历,第三层对应第二指针j从i开始遍历,比较大小,记录最长长度和该字符
代码如下:
#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
int main(void)
{
int n;
cin >> n;
while (n --)
{
int cnt = 0;
char ch;
string str;
cin >> str;
for (int i = 0; i < str.size(); ++ i)
{
int j = i;
while (j < str.size() && str[i] == str[j]) ++ j;
if (j - i > cnt) cnt = j - i, ch = str[i];
i = j - 1;
}
cout << ch << ' ' << cnt << endl;
}
return 0;
}
三:最长单词
概述问题:以’ .'结尾的英文句子,单词之间用空格分隔,求句子中最长的单词,输入长度不超过500,如有多个最长则输出第一个。
输入样例:
I am a student of Peking University.
输出样例:
University
思路 && 做法: 输入一个字符串可以看作输入若干单词,最后一个单词比较特殊,因为有’.’,所以要去掉点才能算一个单词
代码如下:
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
string res, str;
while (cin >> str)
{
if (str.back() == '.') str.pop_back();
//str.back()表示str串的最后一个字符,pop_back为除去它
if (str.size() > res.size()) res = str;
//如果输入串的长度更大就更新res(结果串),res初始为空(0)
}
cout << res << endl;
return 0;
}
四:倒排单词
概述问题:读入一行字符串(只包含字母、空格),倒序输出所有单词,空格照样输出。
输入样例:
I am a student
输出样例:
student a am I
思路 && 做法 : 利用字符串数组,注意字符串数组不等同于字符数组,字符数组每一个单位存放一个字符,字符串数组每一个单位存放一个字符串,与c语言的二维数组功能类似,但是形式上是一维的数组,存放进去后倒序输出即可。记得头文件为
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
string str[100];
int n = 0;
while (cin >> str[n]) ++ n;
for (int i = n - 1; i >= 0; -- i)
cout << str[i] << ' ';
return 0;
}
五:字符串移位包含问题
概述问题:将字符串的第一个字符移动到末尾形成新的字符串称为循环移位,现给定s1, s2,要求判断s1和s2中长串不断循环移位形成的子串能否得到较短串,能则输出true,否则输出false。
输入样例:
AABCD CDAA
输出样例:
true
解释一下:s1串AABCD - > ABCDA - > BCDAA,完成两次循环移位,得到子串CDAA恰好能得到s2串,所以符合条件输出true
思路 && 做法: 首先确定长短串,然后三层循环嵌套,第一层循环完成多次循环移位这一任务,第二层循环完成多次长串子串与短串的比对中,长串长串比对位置移动的任务,第三层循环用来长短串比对中二者的匹配
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
using namespace std;
int main(void)
{
string a, b;
cin >> a >> b;
if (a.size() < b.size()) swap(a, b);//确定长短串
for (int i = 0; i < a.size(); ++ i)
{
a = a.substr(1) + a[0];//摘头添尾
for (int j = 0; j + b.size() <= a.size(); ++ j)
{
int k = 0;
for (; k < b.size(); ++ k)
if (a[j+k] != b[k])//匹配出错则退出
break;
if (k == b.size())//完全匹配,输出true
{
puts("true");
return 0;
}
}
}
//否则,匹配不上输出false
puts("false");
return 0;
}
六:字符串乘方
概述问题:字符串a和b,定义a*b为将a、b相连,定义:(a 0)=””(空字符串),(a n+1)= a ∗ (a n)。举例:假如字符串s = “abcabc”,那么存在字符串a = “abacabc”,使得s = (a 1);a = “abc”,使得s = (a 2),为了满足条件
s = (a n)且保证n最大,输出n的值。输入’.‘结束
输入样例:
abcd
aaaa
ababab
输出样例:
1
4
3
思路 && 做法: 三层循环嵌套,第一层循环用来接收众多字符串,第二层循环来处理算出长度,对字符串等距分段,通过取段数(从1~n),并判断是否等距,比如串长为16,n = 16, 15, 14, 13…当n取到16, 8, 4, 2, 1时能保证等距,确保等距后即可处理,判断串str ?= (str_m n),str_m代表str的前m个字符,其中m = 串长 / n,带入上例可知,当n能保证等距时,m对应取值为1,2,4,8,16,第三层循环完成(str_m n)的计算过程
代码如下:
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
string str;
while (cin >> str, str != ".")//当输入字符串为.时结束
{
int n, len = str.size();
for (n = len; n; -- n)//n从len到0
if (len % n == 0)
{
int m = len / n;
string s = str.substr(0, m);
string r;
for (int i = 0; i < n; ++ i)
r += s;//完成(str_m n)的计算
if (str == r)
{
cout << n << endl;
break;
}
}
}
return 0;
}
七:字符串最大跨距
概述问题:输入共一行,包含三个字符串S,S1,S2,字符串之间用逗号隔开,数据不含空格和逗号,S串长度不超过300,S1和S2长度不超过10计算满足上述条件的最大跨距(即,最大间隔距离:最右边的S2的起始点与最左边的S1的终止点之间的字符数目)。
例如,S = “abcd123ab888efghij45ef67kl”, S1=”ab”, S2=”ef”,其中,S1在S中出现了2次,S2也在S中出现了2次,最大跨距为:18。
输入样例:
abcd123ab888efghij45ef67kl,ab,ef
输出样例:
18
思路 && 做法: 首先是对输入的处理,中间两个逗号,然后进行匹配
s1从前往后做匹配查找,s2从后往前做匹配查找,找到之后将标签1标记在s1最后一个字符上,将标签2标记在s2第一个字符上,此时,距离 = 标签2-标签1 - 1;
代码如下:
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
string s, s1, s2;
char c;
//对输入进行处理
while (cin >> c, c != ',') s += c;
while (cin >> c, c != ',') s1 += c;
while (cin >> c) s2 += c;
if (s.size() < s1.size() || s.size() < s2.size())
puts("-1");//当主(长)串比两个短(从)串短时
else
{
int l = 0;
while (l + s1.size() <= s.size())//从左往右匹配s1
{
int k = 0;
while (k < s1.size())
{
if (s[l+k] != s1[k]) break;
++ k;
}
if (k == s1.size()) break;
++ l;
}
int r = s.size() - s2.size();
while (r >= 0)//从右往左匹配s2
{
int k = 0;
while (k < s2.size())
{
if (s[r+k] != s2[k]) break;
++ k;
}
if (k == s2.size()) break;
-- r;
}
l = l + s1.size() - 1;//该位置设置标签1
//标签2不需要单独设置,就是r对应位置
if (l >= r) puts("-1");
else printf("%d\n", r - l - 1);
}
return 0;
}
八:最长公共字符串后缀
概述问题:输入若干组,输入0结束。
每组输入的第一行是一个整数N,接着N行输入,每行是一个字符串(字符串内不含空白符),每个字符串的长度不超过200。
输入样例:
3
baba
aba
cba
2
aa
cc
2
aa
a
0
输出样例:
ba
a
思路 && 做法: 三层循环嵌套,第一层循环,接受输入数N,当输入为0时结束,第二层循环接受输入的字符串,从第二个开始每一个字符串都与第一个比对,第三层循环就使具体比对内容了
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
using namespace std;
const int INF = 1000000;
int main(void)
{
string s, a;
int n;
while (cin >> n, n)
{
cin >> s;
int Max = INF;
for (int i = 1; i < n; ++ i)
{
int res = 0;
cin >> a;
for (int j = 0; j < s.size() && j < a.size(); ++ j)
{
if (s[s.size() - j - 1] == a[a.size() - j - 1])
++ res;
else break;
}
Max = min(res, Max);
}
if (Max)
cout << s.substr(s.size() - Max) << endl;
else cout << endl;
}
return 0;
}
以上就是这次分享的全部内容了,谢谢观看,一起学习啊~