信息学奥赛第二节 —— 字符串2(s.find() + s.substr() + s.erase() + s.insert() + s.replace())

  • Post author:
  • Post category:其他




前言



上次文章

,以一道例题开始本文。本题需要读者自行了解一下什么是

字典序

。在这里简单介绍一下字典序的比较:

hello > hell



hello < hellp



练习1

原题链接

题目描述

编写程序,针对输入的N个不同的字符串,输出其中字典码最小的字符串。

输入

输入第一行给出正整数N;随后N行,每行给出一个长度小于80的非空字符串,其中不会出现换行符,空格,制表符。

输出

输出字典码最小的字符串

样例输入

5

Li

Wang

Zha

Jin

Xian

样例输出

Jin


解题思路

:C++中的

string

类可以直接进行字符串的比较,故建议直接使用

'>'、'<'

来进行字符串的比较。先输入第一个字符串

S1

,再输入剩下的字符串

S2...Sn

,每次输入

Si

之后都将其与第一个字符串进行比较,若小于第一个字符串,就将其复制给第一个字符串

S1

,最后输出

S1

即可。


AC代码

#include <iostream>
#include <string>

using namespace std;

int main()
{
    int n; cin >> n;//输入组数
    string s1; cin >> s1;//输入第一个字符串
    int x = n - 1;//输入剩下的n - 1个字符
    while (x--)
    {
        string s; cin >> s;
        if (s < s1) s1 = s;
    }
    cout << s1 << endl;//s1保存字典序最小的那个字符串
    return 0;
}


字符串中常见的函数


查找、截取:


  • find(sub)

    —— 查找字符串中子串

    sub

    第一次出现的下标,如果没有,则返回-1

  • find(sub,x)

    —— 从下标

    x

    开始查找子字符串

    sub

  • substr(i,len)

    —— 从下标

    i

    开始,截取长度为

    len

    的子串

  • substr(i)

    —— 从下标

    i

    开始截取子串,截取到最后


插入、删除、替换:


  • erase(i,len)

    —— 从下标

    i

    开始删除长度为

    len

    个字符

  • erase(i)

    —— 从下标

    i

    开始删除下标

    i

    之后的所有字符

  • insert(i,sub)

    —— 在下标为

    i

    的位置插入一个字符串

    sub

  • replace(i,len,,str)

    —— 从下标

    i

    开始,将其后

    len

    个长度的字符替换为

    str


举例说明


s.find(sub)

#include <iostream>
#include <string>

using namespace std;

int main()
{
    string s = "hello world";
    string x = "world";
    
    int p = s.find(x);//在字符串s中查找子串x,若没有则返回-1
    cout << p << endl;//6
    return 0;
}


substr(i,len)截取world

#include <iostream>
#include <string>

using namespace std;

int main()
{
    string s = "hello world";
    string x = "world";
    
    //第一种方法:
    string res1 = s.substr(6,5);//从字符串s第6个位置开始,向后截取5个字符
    cout << res1 << endl;//world
    
    //第二种方法:
    int p = s.find(" ");//先找到字符串s中空格的位置
    string res2 = s.substr(p + 1,5);//从p + 1位置开始,向后截取5个字符
    cout << res2 << endl;//world
    
    //第三种方法:
    string res3 = s.substr(6);//从第6个位置开始截取到最后
    cout << res3 << endl;//world
    return 0;
}


s.erase、s.insert、s.replace:

#include <iostream>
#include <string>

using namespace std;

int main()
{
    string s = "this is a phone";
    
    string res1 = s.substr(5,2);//截取is
    cout << res1 << endl;
    
    s.erase(5,3);//删除is
    cout << s << endl;
    
    s.insert(5,"is ");//插入is
    cout << s << endl;
    
    s.replace(10,5,"book");//替换phone为book
    cout << s << endl;
    return 0;
}

输出:

is

this a phone

this is a phone

this is a book



练习2

原题链接

题目描述

请问在一个父字符串s中是否存在子字符串t。如果存在,则输出子字符串t在父字符串中所有的起始位置,如果不存在,则输出-1。

比如:假设父字符串s = “Go Abc good goole!”,子字符串t = “go”,那么输出位置:

8

13

再比如:假设父字符串s = “Go Abc good goole!”,子字符串t = “hi”,那么输出结果:-1。

输入

第一行输入父字符串的值;

第二行输入子字符串的值;

输出

输出子字符串在父字符串中所有的位置,如果父字符串中不存在子字符串,请输出-1。

样例输入

Go Abc good goole!

go

样例输出

8

13


解题思路

:本题可以使用

KMP

算法来解决。也可以使用上面介绍的几种字符串函数搭配

while

循环来实现。需要注意的是:在

while

循环中,如果写成

pos = s.find(t,pos);

则会

TLE



AC代码

#include <iostream>
#include <string>

using namespace std;

int main()
{
    string s,t;//s代表子串,t代表模式串
    getline(cin,s);
    getline(cin,t);
    
    int pos = s.find(t);
    if (pos == -1) cout << -1 << endl;//子串不存在
    else//pos != -1:子串存在 
    {
        while (pos != -1) 
        {
            cout << pos + 1 << endl;//题目中下标从1开始
            pos = s.find(t,pos + 1);//从pos + 1的位置开始继续搜索
        }
    }
    return 0;
}


练习3

原题链接

题目描述

从键盘输入一个字符串str和一个字符c,删除str中的所有字符c并输出删除后的字符串str。

输入

第一行是一个字符串; (不含空格)

第二行是一个字符。

输出

删除指定字符后的字符串。

样例输入

在这里插入图片描述

样例输出

sdfsdf


AC代码

#include <iostream>
#include <string>

using namespace std;

int main()
{
    string s; char c;//读入字符串以及字符
    getline(cin,s); cin >> c;
    
    int p = s.find(c);//先在字符串中找到第一个目标字符出现的位置
    while (p != -1)
    {
        s.erase(p,1);//删除字符
        p = s.find(c);//更新p的位置
    }
    cout << s << endl;
    return 0;
}


本题的易错点:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>

using namespace std;

int main()
{
    string s; getline(cin,s);
    char c; cin >> c;
    
    int len = s.size();
    for (int i = 0 ;i < len;i++)
        if (s[i] == c) 
            s.erase(i,1);
            
    cout << s << endl;
    return 0;
}


以上代码是错误的

,原因是

s.erase(i,1);

这个是函数,erase删除之后这个字符串的长度就变了。所以正确的思路是每次查找要删除的字符的位置,然后删除,直到找不到为止。



版权声明:本文为smallrain6原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。