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;
}
原文地址:https://www.cnblogs.com/staginner/p/2705438.html