C++中字符串题目小汇(比纯C简单)

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

代码如下:

  1. 偏向于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;
}
  1. 精炼成熟的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;
}

以上就是这次分享的全部内容了,谢谢观看,一起学习啊~

  • 8
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值