Topcoder SRM 327 Div1 300!

题意:给一个字符串,含有大写字母或者问号’?’。一个字符串被定义为ugly,则能在字符串中找到三个连续的元音字符或者五个非元音字符;一个字符串被定义为nice,则它不是ugly的。现在问,可否改将所有’?’变成字符,使得字符串成为nice或ugly的,如果都可以,输出”47”,如果只能一个,输出”UGLY”或”NICE”。

解法:对于是否可为ugly的情况,很简单,将每个’?’都变为元音,看是否存在3个连续的元音,再将每个’?’变为非元音,再看是否存在5个连续的非元音。。对于是否可为nice的情况,用贪心去做即可(不要想复杂,否则可能会进入大坑),首先,可以小证,对于连续的问号(问号数量大于1),一定可以将问号变换,使得字符串为nice。对于单个的问号,即一个问号,左右两边都不是问号,这个时候需要讨论下,贪心下就好了。。写完后一直在看别人代码,发现有更好的写法,不需要预处理什么,直接O(n)扫,用两个变量判一判就行了。

Best Code

#include<string>
using namespace std;
class NiceOrUgly{
public:
    bool isvol(char c){
        return c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U';
    }
    string describe(string s){
        bool can1 = 0;
        int nv, nc;
        nv = nc = 0;
        for(int i = 0; i < s.length() && can1 == 0; i++){
            if(s[i] == '?') nv++, nc++;
            else if(isvol(s[i])) nv++, nc = 0;
            else nv = 0, nc++;
            if(nv >= 3 || nc >= 5) can1 = 1;
        }

        bool can2 = 1;
        nv = nc = 0;
        for(int i = 0; i < s.length() && can2 == 1; i++){
            if(s[i] == '?'){
                if(nv == 2) nv = 0, nc = 1;
                else if(nc == 4) nv = 1, nc = 0;
                else nv = nc = 0;
            }
            else if(isvol(s[i])) nv++, nc = 0;
            else nv = 0, nc++;
            if(nv >= 3 || nc >= 5) can2 = 0;
        }

        if(can1 && can2) return "42";
        else if(can1 && !can2) return "UGLY";
        else return "NICE";
    }
};

你可能感兴趣的:(Topcoder SRM 327 Div1 300!)