PAT A1071 Speech Patterns (25 分) 字符串

60 篇文章 0 订阅

     题目大意:找出给定的字符串中出现次数最多的单词,如果有多个,输出首字符ASCII码最小的单词。这里的单词,是指只含数字和字母字符的字符串。单词之间以非字母和数字字符分开,忽略大小写的差异。

    主要考察的是循环的写法,怎么写这个循环bug能最少。用 for循环遍历思考量较少,找到一个数字或字母字符后,持续向后遍历(while),直到不是数字或字母字符,或者达到了字符串的末尾,这样就得到了一个单词。

AC代码:

#include <iostream>
#include <cstdio>
#include <map>


using namespace std;

bool isAlphanumerical(char &c)
{
    if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z')) return true;
    if(c >= 'A' && c <= 'Z')
    {
        c = c - 'A' + 'a';
        return true;
    }
    return false;
}

int main()
{
    string str;
    getline(cin, str);
    map<string, int> wordToCount;
    int maxCount = 0;
    for (int i = 0; i < str.size(); ++i)
    {
        if(isAlphanumerical(str[i]))
        {
            string word;
            word += str[i++];
            while(isAlphanumerical(str[i]))
            {
                word += str[i++];
                if(i == str.size()) break;
            }
            wordToCount[word]++;
            if(wordToCount[word] > maxCount)
                maxCount = wordToCount[word];
        }
    }
    for(map<string, int>::iterator it = wordToCount.begin(); it != wordToCount.end(); it++)
    {
        if(it->second == maxCount)
        {
            printf("%s %d", it->first.c_str(), maxCount);
            break;
        }
    }

    return 0;
}


如果用状态机的写法,例如初始状态为0,在状态0的条件下找到第一个数字或字母字符后设置状态为1,并记录单词的开始位置start;在状态1的条件下找到第一个非数字或字母字符,设置状态为0,则单词的结束位置是前一个,这样就找到了一个单词。但这样写有一个麻烦,就是原字符串的最后一个字符如果也符合条件,那么也需要被记录 (测试点4),但不会进入状态1->0的判断,所以需要单独拿出来。写法不太简洁。

AC代码:

#include <iostream>
#include <cstdio>
#include <map>


using namespace std;

bool isAlphanumerical(char &c)
{
    if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z')) return true;
    if(c >= 'A' && c <= 'Z')
    {
        c = c - 'A' + 'a';
        return true;
    }
    return false;
}

int main()
{
    string str;
    getline(cin, str);
    map<string, int> wordToCount;
    int maxCount = 0;
    int state = 0, start = 0;
    for (int i = 0; i < str.size(); ++i)
    {
        if(isAlphanumerical(str[i]) && state == 0)
        {
            start = i;
            state = 1;
        }
        else if(!isAlphanumerical(str[i]) && state == 1)
        {
            string word = str.substr(start, i-start);
            wordToCount[word]++;
            if(wordToCount[word] > maxCount)
                maxCount = wordToCount[word];
            state = 0;
        }
        if(i == str.size() - 1)
        {
            string word = str.substr(start, i - start + 1);
            wordToCount[word]++;
            if(wordToCount[word] > maxCount)
                maxCount = wordToCount[word];
        }
    }
    for(map<string,int>::iterator it = wordToCount.begin(); it != wordToCount.end(); it++)
    {
        if(it->second == maxCount)
        {
            printf("%s %d", it->first.c_str(), maxCount);
            break;
        }
    }
    return 0;
}


优化使用循环的代码,从左向右遍历,记录每一个单词的起点和终点,利用内置的类型判断函数 isalnum()和大小写转换函数 tolower()可以少写几行代码:

#include <bits/stdc++.h>

using namespace std;

map<string, int> mp;

int main()
{
    string str;
    getline(cin, str);
    int left = 0, right = left + 1;
    while(left < str.size())
    {
        while(left < str.size() && !isalnum(str[left])) left++;
        right = left;
        while(right < str.size() && isalnum(str[right]))
        {
            str[right] = tolower(str[right]);
            right++;
        }
        right--;
        string word = str.substr(left, right - left + 1);
        mp[word]++;
        left = right + 1;
    }
    int maxCnt = 0;
    string ret;
    for(auto it = mp.begin(); it != mp.end(); it++)
    {
        if(it->second > maxCnt)
        {
            maxCnt = it->second;
            ret = it->first;
        }
    }
    cout << ret << " " << maxCnt;
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值