UVALive 4987 Insults
2012-09-27 12:21
246 查看
UVALive_4981
首先判断一个括号序列是否合法,可以用一个栈来实现。
为了让字典序只大那么一点点,必然保留的前缀长度越长越好,因此可以枚举保留的前缀的长度,接着,除去前缀的下一个字符应该大得越少越好,这一点也可以枚举,如果此时依然合法的话就要看剩下的字符的数量能否让栈中的左括号全部出栈,如果不行的话显然也是不合法的。如果还有多余的字符呢?由于我们已经让前缀的下一个字符比原来的这个位置的字符大了,那么后面的字符的字典序就应该越小越好,所以我们应该在紧邻的位置补类似ae、aaee、aaaeee这样的东西,至于补多长就要依剩余的字符的数量而定了。
首先判断一个括号序列是否合法,可以用一个栈来实现。
为了让字典序只大那么一点点,必然保留的前缀长度越长越好,因此可以枚举保留的前缀的长度,接着,除去前缀的下一个字符应该大得越少越好,这一点也可以枚举,如果此时依然合法的话就要看剩下的字符的数量能否让栈中的左括号全部出栈,如果不行的话显然也是不合法的。如果还有多余的字符呢?由于我们已经让前缀的下一个字符比原来的这个位置的字符大了,那么后面的字符的字典序就应该越小越好,所以我们应该在紧邻的位置补类似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 == -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; }
相关文章推荐
- UVALive - 4987 Evacuation Plan
- UVALive 4987 EvacuationPlan(dp,贪心)
- UVALive - 4987 Evacuation Plan DP+贪心
- UVALive 4987---Evacuation Plan(区间DP)
- UVALive 4987 Evacuation Plan
- UVaLive 6693 Flow Game (计算几何,线段相交)
- 例题1.8 彩色立方体 Colored Cubes UVALive - 3401 暴力打表+暴力搜索+贪心
- UVALive3638 UVA12100 POJ3125 HDU1972 Printer Queue(优先队列+队列)
- UVALive 7008 Tactical Multiple Defense System
- POJ2109 ZOJ2486 UVA113 UVALive3098 Power of Cryptography【数学】
- UVALive 6125 I’ve Got Your Back(gammon) 题解
- UVALive 4731 Cellular Network 【dp】
- UVALive 4887 Soccer 状压+模拟
- UVALive 6424 Russian Dolls 贪心
- hdu 3721 uvalive 5026 building roads
- UVALive 3695 Distant Galaxy 用矩阵的边覆盖二维平面上最多的点 科学的枚举
- UVALive 6507 Passwords
- UVA Live Archive 4015 Cave (树形dp,分组背包)
- UVALive 3523 圆桌骑士
- UVALive 3027 Corporative Network 带权并查集