机试常用算法和题型-字符串专题

字符串专题

1.统计单词频率

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

int main()
{
    string str;

    while(getline(cin,str)){
        int hashTable[26]={0};
        int maxn=-1;
        for(int i=0;i<str.size();i++){
            if(isalpha(str[i])){
                str[i]=tolower(str[i]);
                hashTable[str[i]-'a']++;
                maxn=max(maxn,hashTable[str[i]-'a']);
            }

        }

        for(int i=0;i<26;i++){
            if(hashTable[i]==maxn){
                printf("%c %d\n",i+'a',maxn);
            }
        }

    }

    return 0;
}

#include <iostream>
#include <string>
#include <vector>
#include <ctype.h>
#include <cmath>
using namespace std;

int main()
{
    string str;
    int hashTable[26]={0};
    int anum=0,wnum=0,cntMax=0;
    while(cin>>str){
        anum=anum+str.size();
        wnum++;
        for(int i=0;i<str.size();i++){
            str[i]=tolower(str[i]);
            hashTable[str[i]-'a']++;
            cntMax=max(cntMax,hashTable[str[i]-'a']);
        }
      //这个要用对地方!!,用在前面没处理,少读字符串
        char ch=getchar();
        if(ch=='\n') break;
    }
    printf("字母个数:%d\n",anum);
    printf("单词个数:%d\n",wnum);
    bool nofirst=false;
    printf("最多的字母:");
    for(int i=0;i<26;i++){
        if(hashTable[i]==cntMax){

            if(nofirst){
                printf(",%c",i+'a');
            }else{
                nofirst=true;
                printf("%c",i+'a');
            }
        }
    }
    printf("\n出现的次数:%d\n",cntMax);

    return 0;
}

2.密文加密

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

int main()
{
    string str;

    while(getline(cin,str)){
        for(int i=0;i<str.size();i++){
            if(isalpha(str[i])){
                if(islower(str[i])){
                    str[i]=(str[i]+3-'a')%26+'a';
                }else{
                    str[i]=(str[i]+3-'A')%26+'A';
                }
            }
        }
        cout<<str<<endl;
    }

    return 0;
}

cctype头文件中处理字符函数

[图片上传失败...(image-578378-1587804682906)]

3.find使用,删除指定子串,transform使用

对于字符串string,需要使用string头文件,包含以下常用方法:

s.find(str,[pos]):在字符串s中从第 pos 个字符开始寻找 str ,并返回位置,如果找不到返回-1。pos 可省略,默认为0

s.erase(pos,n):从给定起始位置 pos 处开始删除,要删除字符的长度为n,返回修改后的string对象
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
using namespace std;

int main()
{
    string str;

    while(cin>>str){
        int pos=0;
        string word="gzu";
        //果然字符串还是得要用双引号稳妥,pos放在下面也更稳妥
        while(str.find(word,pos)!=string::npos){
            pos=str.find(word,pos);

            str.erase(pos,3);
        }
        cout<<str<<endl;
    }

    return 0;
}

//进阶版
int main()
{
    string str;

    while(cin>>str){
        int pos=0;
        string word="gzu";
        string temp=str;
        transform(str.begin(),str.end(),str.begin(),::tolower);
      //while ((pos = str1.find("gzu")) != -1)也可!!
        while(str.find(word,pos)!=string::npos){
            pos=str.find(word,pos);
            str.erase(pos,3);
            temp.erase(pos,3);
        }
        cout<<temp<<endl;
    }

    return 0;
}

4.字符串前缀识别

#include <iostream>
#include<string.h>
using namespace std;
int main()
{
    char str[100][100];
    int n;
    while (cin >> n&& n)
    {
        for (int i = 0; i < n; i++)
        {
            cin >> str[i];
        }
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (i == j)continue;//比较不同字符串
                if (str[i][0] == '@')continue;//已经修改过的就不用再判断了
                bool flag = true;
                for (int k = 0; k < strlen(str[i])&& flag; k++)
                {
                    if (str[i][0] == '@')
                        flag = false;
                    if (str[i][k] != str[j][k])
                        flag = false;
                }
                if (flag)
                {
                    str[i][0] = '@';
                }
            }
        }
        int ans = 0;
        for (int i = 0; i < n; i++)
        {
            if (str[i][0] != '@')
                ans++;
        }
        cout << ans << endl;
    }
    return 0;
}

给定字符串找出重复字符和位置,*号法

/*对于给定字符串,找出有重复的字符,并给出其位置*/
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main(){
    string str;
    while(cin>>str){
        int len=str.size();
        for(int i=0;i<len-1;i++){
            bool first=true;
            bool isDup=false;
            if(str[i]!='*'){
                    //i.j不要老搞错
                for(int j=i+1;j<len;j++){
                    if(str[i]==str[j]){
                        isDup=true;
                        str[j]='*';
                        if(first){
                            cout<<str[i]<<","<<i+1<<";"<<str[i]<<","<<j+1;
                            first=false;
                        }else{
                            cout<<";"<<str[i]<<","<<j+1;
                        }
                    }
                }

            }
            if(isDup){
                cout<<endl;
            }
        }
    }

}

5.string循环截取的两种办法

//记录当前位置截取法,有当前位置和新位置,不改变原来字符串
void CutString(string line,vector<string> &subline,char a){
    //a就是截取的标号
    size_t pos=0;
    while(pos<line.length()) {
        size_t curpos=pos;
        pos=line.find(a,curpos);
        if(pos==string::npos)
        {
            pos=line.length();
        }
        subline.push_back(line.substr(curpos,pos-curpos));
        pos++;
    }
}

//查找截取之后删除法,不管咋样,pos还是不要放在判定中
        while(str.find('.')!=-1){
        //观念一直没有改过来,pos是位置,pos-0就是长度,0-pos长度就是pos+!
         //pos用法果然有问题
          pos=str.find('.');
          //下面逻辑没得问题
          temp=str.substr(0,pos);
          arr.push_back(temp);
          str=str.erase(0,pos+1);
        }
        arr.push_back(str);

6.读入用户输入的,以“.”结尾的一行文字,统计一共有多少个单词

2、  #include<stdio.h>
3、  #include<string.h>
4、  int main(){
5、      char s[1000];
6、      int len,a[1000]={0},i,cnt;
7、      gets(s);
8、      len=strlen(s);
9、      printf("len=%d\n",len);
10、     cnt=0;//记录单词数;
11、     i=0;
  //如果是这样计算就不要老想着for循环,while自己i++
12、     while(i<len-1&&s[i]==' '){//去掉开头的空格;
13、         i++;
14、     }
15、         while(i<len-1){
16、             if(s[i]!=' '){//遇到字符;
17、                 a[cnt]+=1;
18、                 i++;
19、             }
20、             else{//遇到空格;
21、                 cnt++;//下一个单词;
22、                 while(i<len-1&&s[i]==' '){//去掉中间的连续空格;
23、                     i++;
24、                 }
25、             }
26、         }
27、         printf("单词个数:%d.\n",cnt+1);
28、         printf("每个单词所含有的字符数是:\n");
29、         for(i=0;i<cnt+1;i++){
30、             printf("%d ",a[i]);
31、         }
32、 }

7.找出数组中最长无重复子串的长度

/*
输出一个整数,代表arr的最长无重复字符的长度。
不要和最长公共子串搞混,这个就是自己的子串
*/
#include<iostream>
using namespace std;
int A[100001];
int main() {
    int n; int length = 0;
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> A[i];
    }
    int start = 0; int i = 1;
    while (i < n) {
        int temp = 1;
        for (int j = start; j < i; j++) {
            if (A[j] == A[i]) {
                start = j + 1;
            }
            else {
                temp++;
            }
            if (temp > length)length = temp;
        }
        i++;
    }
    cout << length;
    return 0;
}

方法二:

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

int main()
{
    int n;
    cin>>n;
    int *arr = new int[n];

    for(int i = 0; i<n; i++)
    {
        int temp;
        cin>>temp;

        arr[i] = temp;
    }

    int length =0;
    int left  = 0;
    int right = 0;
    unordered_set<int> rec;

    while (left < n && right < n)
    {
        int cur = arr[right];
        //终于明白了,end()相当于a[n]指向最后一个后一个元素
        if (rec.end() == rec.find(cur))
        {
            rec.insert(cur);
            right++;
            length = (right - left) > length?(right - left):length;
        }
        else
        {   //没有指向最后一个,也就是说找到了!!,这个意思也就是起点需要后移
            //如果一直都是找到的,那么就得一直后移
            rec.erase(arr[left]);
            left++;
        }
    }


    cout<<length<<endl;
    delete [] arr;
    return 0;
}

8.手机键盘按键,find和hash办法

/*
手机键盘
*/
#include <iostream>

using namespace std;

int main()
{
    string arr[8]={"abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};

    string str;
    while(cin>>str){
        int cnt=0;
        for(int i=0;i<str.size();i++){
            int pos;
             for(int j=0;j<8;j++){
                if(arr[j].find(str[i])!=-1){
                        //找到的意思
                    pos=arr[j].find(str[i]);
                    if(i+1<str.size()&&arr[j].find(str[i+1])!=-1){
                        cnt=cnt+2;
                    }
                }
            }

            cnt=cnt+pos+1;

        }

        cout<<cnt<<endl;
    }

    return 0;
}

好方法:


1其实只需要一个数组就够用了啊。用key顺序记录26个字母按键次数,
2然后判断两个字母是否在同一个按键上,如果在同一个按键上,那么下标差(字母间距)
就等于按键次数差。
#include<iostream>
#include<string>
using namespace std;
int main()
{
    int key[26] = {1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,4,1,2,3,1,2,3,4};
    string str;
    while(cin>>str)
    {
        int count = key[str[0]-'a'];
        for(int i=1;i<str.size();++i)
        {
            count += key[str[i]-'a'];
            if(key[str[i]-'a']-key[str[i-1]-'a']==str[i]-str[i-1])//判断是否在同一个按键上
                count+=2;
        }
        cout<<count<<endl;
    }
}

9.给定一个0字符串,求出全部子串出现次数


/*map方法,自动按照字典序增序
使用substr轻松截取子串,为啥老是忘记了!!*/
#include <iostream>
#include <bits/stdc++.h>
using namespace std;

int main()
{
    string s;
    while(cin>>s){
        map<string,int> m;
        for(int i=0;i<=s.size();i++){
            for(int j=0;j<i;j++){
                m[s.substr(j,i-j)]++;
            }
        }

        for(auto it=m.begin();it!=m.end();it++){
            if(it->second>1)
                cout<<it->first<<" "<<it->second<<endl;
        }
    }

    return 0;
}

方法二:朴素手写方法

//一前一后两个指针来截取子串

#include <iostream>
#include <bits/stdc++.h>
#define N 5050

using namespace std;

struct STR{
    string s;
    unsigned cnt;
}buf[N]; //子串集合

int n; //子串数量
string str;  //读取的字符串
string child;  //临时存储子串


void MakeChild(int from,int len){
    child.clear();
    for(int i=0;i<len;i++){
            //果然在于这里的处理方式
        child=child+str[from+i];
    }
}

bool cmp(STR a,STR b){
    return a.s<b.s;
}

void letsGo(){
    //生成子串列表并完成统计
    int len=str.size();
    for(int i=1;i<len;i++){
        //i是子串长度
        for(int from=0;from+i<=len;from++){
            MakeChild(from,i);  //生成子串
            bool repeat=false;  //用来检查这个子串以前是否出现
            for(int i=0;i<n;i++){
                if(buf[i].s==child){
                    buf[i].cnt++;
                    repeat=true;
                    break;
                }
            }
            if(!repeat){
                //这个字串以前没有出现过
                buf[n].cnt=1;
                buf[n].s=child;
                n++;
            }
        }
    }


}

int main()
{
    while(cin>>str){
        n=0;  //子串个数
        letsGo();
        sort(buf,buf+n,cmp);
        for(int i=0;i<n;i++){
            if(buf[i].cnt>1){
                cout<<buf[i].s<<" "<<buf[i].cnt<<endl;
            }
        }
    }
    return 0;
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,682评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,277评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,083评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,763评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,785评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,624评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,358评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,261评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,722评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,900评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,030评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,737评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,360评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,941评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,057评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,237评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,976评论 2 355

推荐阅读更多精彩内容