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;
    }
  • 相关阅读:
    JS控制文本框输入的内容
    JavaScript属性
    无缝滚动
    CCS实例,网页栏目
    CSS特效
    HTML技巧
    如何解决问题
    判断输入的字符是不是数字
    删除txt文件内容
    能组成几个单词
  • 原文地址:https://www.cnblogs.com/staginner/p/2705438.html
Copyright © 2011-2022 走看看