zoukankan      html  css  js  c++  java
  • UVALive 4987 Insults

    UVALive_4981

        首先判断一个括号序列是否合法,可以用一个栈来实现。

        为了让字典序只大那么一点点,必然保留的前缀长度越长越好,因此可以枚举保留的前缀的长度,接着,除去前缀的下一个字符应该大得越少越好,这一点也可以枚举,如果此时依然合法的话就要看剩下的字符的数量能否让栈中的左括号全部出栈,如果不行的话显然也是不合法的。如果还有多余的字符呢?由于我们已经让前缀的下一个字符比原来的这个位置的字符大了,那么后面的字符的字典序就应该越小越好,所以我们应该在紧邻的位置补类似ae、aaee、aaaeee这样的东西,至于补多长就要依剩余的字符的数量而定了。

    #include<stdio.h>
    #include<string.h>
    #define MAXD 1000010
    int N, first[MAXD], e, next[MAXD], num[MAXD];
    char b[MAXD], st[MAXD], *set = "eio", ch[128];
    void add(int cur, char ch)
    {
        st[e] = ch;
        next[e] = first[cur], first[cur] = e ++;
    }
    int pre()
    {
        int i;
        if(b[1] != 'a' && b[1] != 'i') return 0;
        add(1, b[1]);
        num[1] = 1, num[0] = 0;
        for(i = 2; i <= N; i ++)
        {
            first[i] = first[i - 1];
            if(b[i] == 'a' || b[i] == 'i') add(i, b[i]), num[i] = num[i - 1] + 1;
            else
            {
                if(b[i] == 'e' && (first[i] == -1 || st[first[i]] != 'a')) return 0;
                if(b[i] == 'o' && (first[i] == -1 || st[first[i]] != 'i')) return 0;
                first[i] = next[first[i]], num[i] = num[i - 1] - 1;
            }
        }
        return first[N] == -1;
    }
    void solve()
    {
        int i, j, k;
        N = strlen(b + 1);
        memset(first, -1, sizeof(first[0]) * (N + 1)), e = 0;
        if(!pre())
        {
            printf("INVALID\n");
            return ;
        }
        for(i = N - 1; i >= 0; i --)
        {
            for(j = 0; j < 3; j ++)
                if(set[j] > b[i + 1])
                {
                    if(set[j] == 'i')
                    {
                        if(num[i] > N - i - 2) continue;
                        add(i, set[j]), ++ num[i];
                        for(k = 1; k <= i; k ++) printf("%c", b[k]);
                        printf("i");
                        for(k = 0; k < N - i - 1 - num[i]; k += 2) printf("a");
                        for(k = 0; k < N - i - 1 - num[i]; k += 2) printf("e");
                        for(k = first[i]; k != -1; k = next[k]) printf("%c", ch[st[k]]);
                        printf("\n");
                        return ;
                    }
                    else
                    {
                        if(num[i] > N - i) continue;
                        if(set[j] == 'e' && (first[i] == -1 || st[first[i]] != 'a')) continue;
                        if(set[j] == 'o' && (first[i] == -1 || st[first[i]] != 'i')) continue;
                        first[i] = next[first[i]], -- num[i];
                        for(k = 1; k <= i; k ++) printf("%c", b[k]);
                        printf("%c", set[j]);
                        for(k = 0; k < N - i - 1 - num[i]; k += 2) printf("a");
                        for(k = 0; k < N - i - 1 - num[i]; k += 2) printf("e");
                        for(k = first[i]; k != -1; k = next[k]) printf("%c", ch[st[k]]);
                        printf("\n");
                        return ;
                    }
                }
        }
        printf("ULTIMATE\n");
    }
    int main()
    {
        int t;
        ch['a'] = 'e', ch['e'] = 'a', ch['i'] = 'o', ch['o'] = 'i';
        scanf("%d", &t);
        while(t --)
        {
            scanf("%s", b + 1);
            solve();
        }
        return 0;
    }
  • 相关阅读:
    leetcode 851. Loud and Rich
    674. 最长连续递增序列
    896. 单调数列
    905. 按奇偶排序数组
    917. 仅仅反转字母
    922. 按奇偶排序数组 II
    925. 长按键入
    929. 独特的电子邮件地址
    933. 最近的请求次数
    自己动手丰衣足食写java贪吃蛇
  • 原文地址:https://www.cnblogs.com/staginner/p/2705438.html
Copyright © 2011-2022 走看看