字符串特训

1.单词替换
1.1题目描述

输入一个字符串,以回车结束(字符串长度<=100)。该字符串由若干个单词组成,单词之间用一个空格隔开,所有单词区分大小写。现需要将其中的某个单词替换成另一个单词,并输出替换之后的字符串。
输入描述:
多组数据。每组数据输入包括3行,
第1行是包含多个单词的字符串 s,
第2行是待替换的单词a,(长度<=100)
第3行是a将被替换的单词b。(长度<=100)

s, a, b 最前面和最后面都没有空格.
输出描述:
每个测试数据输出只有 1 行,
将s中所有单词a替换成b之后的字符串。
示例1
输入
You want someone to help you
You
I
输出
I want someone to help you

1.2思路

首先将输入的字符串根据空格符进行切割,将分割之后的单词存储在一个vector中,然后遍历vector将指定的单词替换为目标单词。对于字符串的相等采用string类型的’='运算符直接进行比较可以省去很多麻烦。

1.3代码
#include <iostream>
#include <vector>
#include <string>
#define N 101
using namespace std;

string str,a,b;
vector<string> V;
int main()
{
    getline(cin,str);
    cin>>a>>b;
    int len=str.length();
    V.push_back("");//初始化字符串头部
    for(int i=0,j=0;i<len;i++){
        //            cout<<":"<<str[i]<<endl;
        if(str[i]!=' '){
            V[j]+=str[i];
        }
        else{
            V.push_back("");//初始化字符串头部
            j++;
        }
    }
    for(int i=0;i<V.size();i++){
        if(V[i]==a)
            V[i]=b;
    }

    for(int i=0;i<V.size();i++){
        cout<<V[i]<<" ";
    }
    return 0;
}
2.字符串排序
2.1题目描述

题目描述
编写一个程序,将输入字符串中的字符按如下规则排序(一个测试用例可能包含多组数据,请注意处理)。
规则 1 :英文字母从 A 到 Z 排列,不区分大小写。
如,输入: Type 输出: epTy
规则 2 :同一个英文字母的大小写同时存在时,按照输入顺序排列。
如,输入: BabA 输出: aABb
规则 3 :非英文字母的其它字符保持原来的位置。
如,输入: By?e 输出: Be?y
样例:
输入:
A Famous Saying: Much Ado About Nothing(2012/8).
输出:
A aaAAbc dFgghh : iimM nNn oooos Sttuuuy (2012/8).
输入描述:
输出描述:
示例1
输入
A Famous Saying: Much Ado About Nothing (2012/8).
输出
A aaAAbc dFgghh: iimM nNn oooos Sttuuuy (2012/8).

2.2思路

首先对于需要排序的字符我们将其存储起来,然后排序的时候统一根据其转化为小写字母的大小进行排序,注意由于排序的前后相等的字母应该保持和原字符串中一致的顺序,因此这里的排序应该采用stable_sort()函数。

2.3代码
#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;

int IsLetter(char c){
    if(c>='a'&&c<='z')return 1;//小写字母
    else if(c>='A'&&c<='Z')return 2;//大写之牧野
    else  return 3;
}

bool cmp(char a,char b){//统一根据小写字母形式来比较大小
    if(IsLetter(a)==2)a=a-'A'+'a';
    if(IsLetter(b)==2)b=b-'A'+'a';
    return a<b;
}

int main()
{
    char str[501];
    char buf[501];
    int idx2buf=0;
    while(gets(str)){
        idx2buf=0;
        int len=strlen(str);
        for(int i=0;i<len;i++){

            if(IsLetter(str[i])==1||IsLetter(str[i])==2){
                buf[idx2buf++]=str[i];
            }
        }
        stable_sort(buf,buf+idx2buf,cmp);
        int idx2out=0;
        for(int i=0;i<len;i++){
            if(IsLetter(str[i])==3)
                cout<<str[i];
            else
                cout<<buf[idx2out++];
        }
        cout<<endl;
    }
    return 0;
}
/*
A Famous Saying: Much Ado About Nothing (2012/8).
*/

3.字符串排序(根据长度)
3.1题目描述

先输入你要输入的字符串的个数。然后换行输入该组字符串。每个字符串以回车结束,每个字符串少于一百个字符。 如果在输入过程中输入的一个字符串为“stop”,也结束输入。 然后将这输入的该组字符串按每个字符串的长度,由小到大排序,按排序结果输出字符串。
输入描述:
字符串的个数,以及该组字符串。每个字符串以‘\n’结束。如果输入字符串为“stop”,也结束输入.
输出描述:
可能有多组测试数据,对于每组数据,
将输入的所有字符串按长度由小到大排序输出(如果有“stop”,不输出“stop”)。

根据输入的字符串个数来动态分配存储空间(采用new()函数)。每个字符串会少于100个字符。
测试数据有多组,注意使用while()循环输入。
示例1
输入
复制
5
sky is grey
cold
very cold
stop
3
it is good enough to be proud of
good
it is quite good
输出
复制
cold
very cold
sky is grey
good
it is quite good
it is good enough to be proud of

3.2思路

利用vector来模拟动态链表,然后调用sort函数根据字符串的长度进行排序

3.3代码
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;

vector<string> V;

bool cmp(string a,string b){

    return a.length()<b.length();
}

int main()
{
    string str;
    int n;
    while(cin>>n){
        getchar();//注意,cin是遇到回车或空格作为结束的,而回车仍然留在缓冲区内部,因此需要吸收回车。
        V.clear();
        for(int i=1;i<=n;i++){
            getline(cin,str);
            if(str!="stop"){
                V.push_back(str);
            }
            else{
                break;
            }
        }
        sort(V.begin(),V.end(),cmp);
        for(int i=0;i<V.size();i++){
            cout<<V[i]<<endl;
        }
    }
    return 0;
}
/*
5
sky is grey
cold
very cold
stop
3
it is good enough to be proud of
good
it is quite good
*/

4.String Matching
4.1题目描述

Finding all occurrences of a pattern in a text is a problem that arises frequently in text-editing programs. Typically,the text is a document being edited,and the pattern searched for is a particular word supplied by the user. We assume that the text is an array T[1…n] of length n and that the pattern is an array P[1…m] of length m<=n.We further assume that the elements of P and T are all alphabets(∑={a,b…,z}).The character arrays P and T are often called strings of characters. We say that pattern P occurs with shift s in the text T if 0<=s<=n and T[s+1…s+m] = P[1…m](that is if T[s+j]=P[j],for 1<=j<=m). If P occurs with shift s in T,then we call s a valid shift;otherwise,we calls a invalid shift. Your task is to calculate the number of vald shifts for the given text T and p attern P.
输入描述:
For each case, there are two strings T and P on a line,separated by a single space.You may assume both the length of T and P will not exceed 10^6.
输出描述:
You should output a number on a separate line,which indicates the number of valid shifts for the given text T and pattern P.
示例1
输入
复制
abababab abab
输出
复制
3

4.2思路

从左往右扫描一遍,对每个存在匹配的地方再采用一层循环进行遍历

4.3代码

以下是我手写的代码:

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string T,P;
    cin>>T>>P;
//    getline(cin,T);
//    getline(cin,P);
    int lent=T.length();
    int lenp=P.length();

    int acceql=0;
    int ans=0;
    for(int i=0;i<lent;i++){
        if(T[i]==P[acceql]&&i+lenp<=lent){
            acceql++;
            while(acceql!=lenp){
                if(T[i+acceql]!=P[acceql])
                    break;
                acceql++;
            }
            if(acceql==lenp)ans++;
            acceql=0;
        }
    }
    printf("%d\n",ans);

    return 0;
}
/*
abababab abab
*/

这是参考网上的精简版本代码,主要还是采用了string类中封装的find(string s,int x)函数,其中x表示查找的目标下标从x开始。

#include<iostream>
using namespace std;
#include<string>

int main(){
    string s,p;
    while(cin>>s>>p){
        int cnt=0,pos=s.find(p);
        while(pos!=string::npos){//string::npos=-1,
            cnt++;
            pos = s.find(p,pos+1);
        }
        cout<<cnt<<endl;
    }
}
/*
abababab abab
*/

说到字符串匹配,那么有个KMP算法不得不提,这里直接放出代码,有兴趣的读者可以自行查阅相关的资料进行学习。

链接:https://www.nowcoder.com/questionTerminal/00438b0bc9384ceeb65613346b42e88a?toCommentId=2668548
来源:牛客网

//KMP算法
#include <iostream>
#include <string>
#define N 10001
#define M 101
using namespace std;
 
int Next[M];
string a,b;
 
void getNext(int n){
 
    int i=0,j=-1;
    Next[0]=-1;
    while(i<n){
        if(j==-1||b[i]==b[j]){
            i++;
            j++;
            Next[i]=j;
        }
        else{
            j=Next[j];
        }
    }
}
 
int KMPSearch(int n,int m){
 
    int ans=0;
    int i=0,j=0;
    while(i<n){//&&j<m
        if(j==-1||a[i]==b[j]){
            i++;
            j++;
        }
        else{
            j = Next[j];
        }
        if(j==m){//一次匹配
            ans++;
            i = i-j+1;
            j = 0;
        }
    }
 
    return ans;
}
 
int main()
{
 
    while(cin>>a>>b){
        int lenA  = a.size();
        int lenB  = b.size();
        getNext(lenB);
        cout<<KMPSearch(lenA,lenB)<<endl;;
 
    }
 
    return 0;
}
/*
aaaaaaa
a
*/
5.字符串排序
5.1题目描述

哈利波特在魔法学校的必修课之一就是学习魔咒。据说魔法世界有100000种不同的魔咒,哈利很难全部记住,但是为了对抗强敌,他必须在危急时刻能够调用任何一个需要的魔咒,所以他需要你的帮助。 给你一部魔咒词典。当哈利听到一个魔咒时,你的程序必须告诉他那个魔咒的功能;当哈利需要某个功能但不知道该用什么魔咒时,你的程序要替他找到相应的魔咒。如果他要的魔咒不在词典中,就输出“what?”
输入描述:
首先列出词典中不超过100000条不同的魔咒词条,每条格式为:

[魔咒] 对应功能

其中“魔咒”和“对应功能”分别为长度不超过20和80的字符串,字符串中保证不包含字符“[”和“]”,且“]”和后面的字符串之间有且仅有一个空格。词典最后一行以“@END@”结束,这一行不属于词典中的词条。
词典之后的一行包含正整数N(<=1000),随后是N个测试用例。每个测试用例占一行,或者给出“[魔咒]”,或者给出“对应功能”。
输出描述:
每个测试用例的输出占一行,输出魔咒对应的功能,或者功能对应的魔咒。如果魔咒不在词典中,就输出“what?”
示例1
输入
复制
[expelliarmus] the disarming charm
[rictusempra] send a jet of silver light to hit the enemy
[tarantallegra] control the movement of one’s legs
[serpensortia] shoot a snake out of the end of one’s wand
[lumos] light the wand
[obliviate] the memory charm
[expecto patronum] send a Patronus to the dementors
[accio] the summoning charm
@END@
4
[lumos]
the summoning charm
[arha]
take me to the sky
输出
复制
light the wand
accio
what?
what?

5.2思路

采用字典映射进行相关操作,注意在输入整数之后要采用getchar()吸收回车符。

5.3代码
#include <iostream>
#include <map>
using namespace std;

map<string,string> Mapping;
int main()
{
    string a,b,c;
    while(getline(cin,a)){
        if(a=="@END@")break;
        b = a.substr(a.find("] ")+2);//提取后半部分
        c = a.substr(1,a.find("] ")-1);//提取前部分,顺便去掉括号
        Mapping[c]=b;
        Mapping[b]=c;
    }
    int n;
    cin>>n;
    getchar();
    for(int i=0;i<n;i++){
        getline(cin,a);
        if(a.find('[')!=-1){//查询某个字符在字符串中是否存在
            if(Mapping.count(a)==1)//查询map中某key是否存在
                cout<<Mapping[a]<<endl;
            else
                cout<<"what?"<<endl;
        }
        else{
            if(Mapping.count(a)==1)
                cout<<Mapping[a]<<endl;
            else
                cout<<"what?"<<endl;
        }
    }
    return 0;
}
/*
[expelliarmus] the disarming charm
[rictusempra] send a jet of silver light to hit the enemy
[tarantallegra] control the movement of one's legs
[serpensortia] shoot a snake out of the end of one's wand
[lumos] light the wand
[obliviate] the memory charm
[expecto patronum] send a Patronus to the dementors
[accio] the summoning charm
@END@
4
[lumos]
the summoning charm
[arha]
take me to the sky
*/
2.字符串排序
6.1题目描述

编一个程序,读入用户输入的,以“.”结尾的一行文字,统计一共有多少个单词,并分别输出每个单词含有多少个字符。 (凡是以一个或多个空格隔开的部分就为一个单词)
输入描述:
输入包括1行字符串,以“.”结束,字符串中包含多个单词,单词之间以一个或多个空格隔开。
输出描述:
可能有多组测试数据,对于每组数据,
输出字符串中每个单词包含的字母的个数。
示例1
输入
hello how are you.
输出
5 3 3 3

6.2思路

采用istringstream 对字符串按照空格进行分割,输出每个单词的长度,最后一个长度-1.

6.3代码
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

int main()
{
    string line;

    while (getline(cin, line)) {

        istringstream sin(line);
        vector<string> v;
        string s;
        while (sin >> s)
            v.push_back(s);

        for (int i = 0; i < v.size()-1; ++i) {
            cout <<v[i].length()<< ' ';
        }
        cout <<v[v.size()-1].length()-1<<endl;
    }

    return 0;
}

7.字符串排序
7.1题目描述

输入一个英文句子,把句子中的单词(不区分大小写)按出现次数按从多到少把单词和次数在屏幕上输出来,要求能识别英文句号和逗号,即是说单词由空格、句号和逗号隔开。
输入描述:
输入有若干行,总计不超过1000个字符。
输出描述:
输出格式参见样例。
示例1
输入
A blockhouse is a small castle that has four openings through which to shoot.
输出
a:2
blockhouse:1
castle:1
four:1
has:1
is:1
openings:1
shoot:1
small:1
that:1
through:1
to:1
which:1

7.2思路

首先采用istringstream分割空格符得到单个的单词,采用algorithm库中的transform方法将字母统一转化为小写形式,随后去掉单词尾部的逗号或者句号,然后利用map<string,struct>的映射来统计每一个单词的数量[然后为了对单词根据字典顺序进行排序,将结构体转存在vector中,然后根据sort函数进行排序,最后输出结果即可]括号中的内容其实可以省略,因为map其实就是根据key的字典顺序进行排序,所以可以直接调用map的迭代器,直接遍历map即可。

7.3代码
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <sstream>
using namespace std;

struct word{
    string str;
    int counter;
}buf[201];

bool cmp(word a,word b){
        return a.str<b.str;
}

map<string,word> M;
int main()
{
    printf("%d",'a');
    vector<string> V;
    string str;
    while(getline(cin,str)){
        istringstream sin(str);
        string s;
        //分割空格
        while(sin>>s){
            if(s[s.length()-1]==','||s[s.length()-1]=='.'){
                s=s.substr(0,s.length()-1);
            }
            //统一转为小写
            transform(s.begin(), s.end(), s.begin(), ::tolower);
            V.push_back(s);
        }
        for(int i=0;i<V.size();i++){
            if(M.count(V[i])!=1){
                M[V[i]].str=V[i];
                M[V[i]].counter=1;
            }
            else{
                M[V[i]].counter++;
            }
        }
        //按照字典顺序遍历输出map中的元素
        for(auto it=M.begin();it!=M.end();it++){
            cout<<it->second.str<<":"<<it->second.counter<<endl;
        }

    }
    return 0;
}
/*
A blockhouse is a small castle that has four openings through which to shoot.
*/

最后再讲讲字符串处理中比较实用高效的技巧,就是实现类似于python中的split©函数的功能,
即根据指定的分隔符对字符串进行分割,得到其对应的Token。这些功能主要要用到字符串流头文件
sstream中的stringstream来进行处理,首先是根据空格进行分割

#include <iostream>
#include <string>
#include <sstream>

using namespace std;

int main()
{
    string str="ads vds vd sv s dv cd";
    stringstream ss(str);
    string Token;
    while(ss>>Token){
        cout<<Token<<"-";
    }
    cout<<endl;
    return 0;
}

然后是根据指定的字符进行分割,这里以逗号为例

#include <iostream>
#include <string>
#include <sstream>

using namespace std;

int main()
{
    string str="ads,vds,vdsv,sdv,cd";
    stringstream ss(str);
    string Token;
    while(getline(ss,Token,',')){
        cout<<Token<<" ";
    }
    cout<<endl;

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值