题目链接:https://vjudge.net/problem/FZU-1989
Accept: 79 Submit: 399
Time Limit: 4000 mSec Memory Limit : 32768 KB
Problem Description
Usually, in programming contests all you wait is “AC” (abbreviation of AekdyCoin).We find that boring.
In this task we do the opposite. We will give you a string consists of only uppercase letters. You should remove some letters so that there is no “AC” in the result string. Return the result string with the longest length. If there is more than one string with the longest length, return lexicographically smallest one.
Input
Output
Sample Input
Sample Output
Source
FOJ有奖月赛-2010年11月题意:
给出一个只含大小字母的字符串,求删除最少的字符,使得字符串里面不含有“AC”子串,如果有多个答案,求出字典序最小。
题解:
1.可知,对于答案有影响的,只有“AACCCACAAAACACA……”以A为开始,迭代若干次,然后又到C迭代若干次,一直重复,直到不再出现A或C。
2.为了方便操作,将:“AACCCACAAAACACA……”串缩成“ACACAC……”串,即每个字符中都有一个权值,代表其里面有多少个字符。可知,要使得“ACACAC……”最终不含有“AC”,那么它的最终形式只能为“CA”,其中C、A都有各自的权值,代表其出现次数。
3.根据第2点,只需对每个“AACCCACAAAACACA……”缩成“ACACAC……”,然后每个枚举每个C的位置,前面全部为C,后面全部为A,取两者之和的最大值,即为最终的“CA”段。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <cmath> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const int INF = 2e9; 15 const LL LNF = 9e18; 16 const int MOD = 1e9+7; 17 const int MAXN = 1e5; 18 19 char s[MAXN], ans[MAXN]; 20 int sum[MAXN], t1[MAXN], t2[MAXN]; 21 int main() 22 { 23 int T, kase = 0; 24 scanf("%d", &T); 25 while(T--) 26 { 27 scanf("%s", s); 28 int A = 0, C = 0, tot = 0; 29 for(int i = 0; s[i]; i++) 30 { 31 if(s[i]!='A') //把对答案没影响的先存起来 32 { 33 ans[tot++] = s[i]; 34 continue; 35 } 36 37 int cnt = 0; 38 while(s[i]=='A') //找出ACACAC段,并统计个数 39 { 40 A = C = 0; 41 while(s[i]=='A') A++, i++; 42 while(s[i]=='C') C++, i++; 43 sum[++cnt] = A; 44 sum[++cnt] = C; 45 } 46 47 t1[0] = 0; //求C的前缀和 48 for(int j = 2; j<=cnt; j+=2) 49 t1[j] = t1[j-2]+sum[j]; 50 t2[cnt+1] = 0; //求A的后缀和 51 for(int j = cnt-1; j>=1; j-=2) 52 t2[j] = t2[j+2]+sum[j]; 53 54 int len = 0, lenc = 0; 55 for(int j = 0; j<=cnt; j += 2) //枚举每个C的位置,使得前面全为C,后面全为A,取最大长度 56 { 57 if(t1[j]+t2[j+1]>len) 58 { 59 len = t1[j]+t2[j+1]; 60 lenc = t1[j]; 61 } 62 } 63 //求最长的"CA"串: 64 for(int j = 0; j<lenc; j++) //得到C和A各自的长度后,放到答案串里面。 65 ans[tot++] = 'C'; 66 for(int j = 0; j<len-lenc; j++) 67 ans[tot++] = 'A'; 68 ans[tot++] = s[i]; //由于最后一个字符即不是'A'也不是'C',所以才会退出循环,因此把它补上,否则会有遗漏。 69 } 70 ans[tot] = 0; //注意在答案结尾加上结束符。 71 72 printf("Case %d: ", ++kase); 73 puts(ans); 74 } 75 }