前言
接
上次文章
,以一道例题开始本文。本题需要读者自行了解一下什么是
字典序
。在这里简单介绍一下字典序的比较:
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删除之后这个字符串的长度就变了。所以正确的思路是每次查找要删除的字符的位置,然后删除,直到找不到为止。