题目

句子仅由小写字母('a' 到 'z')、数字('0' 到 '9')、连字符('-')、标点符号('!'、'.' 和 ',')以及空格(' ')组成。每个句子可以根据空格分解成 一个或者多个 token ,这些 token 之间由一个或者多个空格 ' ' 分隔。

如果一个 token 同时满足下述条件,则认为这个 token 是一个有效单词:

  • 仅由小写字母、连字符和/或标点(不含数字)。
  • 至多一个 连字符 '-' 。如果存在,连字符两侧应当都存在小写字母("a-b" 是一个有效单词,但 "-ab" 和 "ab-" 不是有效单词)。
  • 至多一个 标点符号。如果存在,标点符号应当位于 token 的 末尾 。

这里给出几个有效单词的例子:"a-b."、"afad"、"ba-c"、"a!" 和 "!" 。

给你一个字符串 sentence ,请你找出并返回 sentence 中 有效单词的数目 。

来源:力扣(LeetCode)


解答

先根据空格,将句子拆分成一个个伪单词,再对每一个分割后的“伪单词”进行有效性判定即可,最后返回数目即可。

代码如下:

class Solution {
public:
    bool isRight(string &s) {
        int n = s.size();
        int hy = 0;

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

            // 如果是分隔符,只能出现依次,且左右必须为小写字母
            if (s[i] == '-') {
                if (hy > 0) {
                    return false;
                } else {
                    hy++;
                }

                if (i == 0 || i == n - 1) {
                    return false;
                }

                if (!(s[i - 1] >= 'a' && s[i - 1] <= 'z' && s[i + 1] >= 'a' && s[i + 1] <= 'z')) {
                    return false;
                }
            }

            // 如果是标点符号,必须是最后一位
            if (s[i] == '!' || s[i] == ',' || s[i] == '.') {
                if (i != n - 1) {
                    return false;
                }
            }

            // 不能是数字
            if (s[i] >= '0' && s[i] <= '9') {
                return false;
            }
        }

        return true;
    }

    int countValidWords(string sentence) {
        int ret = 0;
        stringstream ss(sentence);
        string tmp;

        while (getline(ss, tmp, ' ')) {
            if (tmp[0] == '\0') {
                continue;
            }
            if (isRight(tmp)) {
                ret++;
            }
        }

        return ret;
    }
};