P1575题解

· · 题解

题目传送门

博客食用更佳

此题C党的题解大部分都是用栈来完成的,那么本蒟蒻就来写一个与所有题解都不同的方法。

大致思路:

  1. 首先读入一整行字符串。
  2. 进行特判,如果开头或末尾即为andor,或末尾为not,则直接输出error
  3. 找出所有的not,如果not后有orand,直接输出error;如果存在多个not的情况,则把每两个not删除。最后只剩一个或零个not,若剩一个not,则把后边的一个单词反转(即truefalse互换),并把not改为"   "(三个空格)。
  4. 找出所有的 and,如果and前面的第一个单词与后面的第一个单词都是true,那么把and以及任意一个true全部赋值为空格,例如,true and true变为true         (9个空格)。
  5. 找出所有的or,方法与and基本一致。
  6. 最后判断字母t与字母f的个数,如果二者都有或任意一者多余一个,则输出error,否则有1个t就输出true,有1个f就输出false

注意:我们只需判断单词中的几个字母即可判断该单词为什么,因此不需要把整个单词分离判断。

步骤1&&步骤2(输入并特判):

//input
    getline(cin, s);
    int len = s.size();
    if (s[0] == 'a' || s[0] == 'o' || s[len - 1] == 'd' || s[len - 1] == 'r' || s[len - 1] == 't') {
        cout << "error";
        return 0;
    }

步骤3(处理not):

//not
    for (int i = 0; i < len; i++) {
        if (s[i] == 'n' && s[i + 1] == 'o') {
            int j = i + 4;
            while (s[j] == ' ') j++;
            if (s[j] == 't')
                s[j] = 'f', s[j + 1] = 'a', s[j + 2] = 's', s[j + 3] = 'e', s[i] = s[i + 1] = s[i + 2] = ' ';
                //因为"true"是4个字母,"false"是5个字母,而中间的"l"没有用,所以可以这样做
            else if (s[j] == 'f')
                s[j] = 't', s[j + 1] = 'r', s[j + 2] = 'r', s[j + 3] = 'u', s[j + 4] = 'e', s[i] = s[i + 1] = s[i + 2] = ' ';
                //道理同上
            else if (s[j] == 'n')
                s[i] = s[i + 1] = s[i + 2] = s[j] = s[j + 1] = s[j + 2] = ' ';
            else {
                cout << "error";
                return 0;
            }
        }
    }

步骤4(处理and):

//and
    for (int i = 1; i < len; i++) {
        if (s[i] == 'a' && s[i + 1] == 'n') {
            int j = i - 2, k = i + 4;
            while (s[j] == ' ') j--;//此时j为and上一个字母的末尾下标
            while (s[k] == ' ') k++;//此时k为and后一个字母的首位下标
            if (s[k] == 'a' && s[k + 1] == 'n') {
                cout << "error";
                return 0;
            }//如果and后面还有and,就输出"error"
            while (s[j] != ' ' && j != 0) j--;//此时j为and上一个字母的首位下标
            while (s[k] != ' ' && k != len - 1) k++;//此时j为and上一个字母的末位下标
            if (j != 0)
                j++;
            if (k != len - 1)
                k--;
            bool flag1 = false, flag2 = false;
            if (s[j] == 't' && s[j + 1] == 'r')
                flag1 = true;
            if (s[k] == 'e' && s[k - 1] == 'u')
                flag2 = true;
            if (flag1 && flag2) {
                s[j] = 't', s[j + 1] = 'r', s[j + 2] = 'u', s[j + 3] = 'e';
                for (int l = j + 3 + 1; l <= k; l++)
                    s[l] = ' ';
            }
            else {
                s[j] = 'f', s[j + 1] = 'a', s[j + 2] = 'l', s[j + 3] = 's', s[j + 4] = 'e';
                for (int l = j + 4 + 1; l <= k; l++)
                    s[l] = ' ';
            }
        }
    }

步骤5(处理or):

此步骤与步骤4几乎一模一样,将步骤4稍微修改即可,这里留给读者自己思考。

步骤6(输出):

//output
    int t[200] = { 0 };//这里用了一个桶来统计字母出现的数量,t[s]表示为字母s出现的次数
    for (int i = 0; i < len; i++) {
        if (s[i] != ' ')
            t[s[i]]++;
    }
    if (t['t'] > 1 || t['f'] > 1 || (t['t'] >= 1 && t['f'] >= 1)) {
        cout << "error";
        return 0;
    }
    else if (t['t'] == 1)
        cout << "true";
    else
        cout << "false";