题目:给一个只有大写字母的字符串。删除一些字母,使得结果字符串中没有“AC”。返回最长的结果字符串。如果有最长的 长度超过一个字符串,返回字典序最小的一个。
条件:1,没有AC 2,返回删除后最长的字符串,如果有多个解是一样长的就返回字典顺序
输入:T 有T组数据T <= 100 接下来T行大写字符串(字符串长度不超过10000)
输出:case 数字:删除后的字符串
思路:遇到需要删除的情况无非就是类似于ACCCACCAAAC这种长串的AC串,仔细思考其实不难发现,删除之后有两种情况,一个就是所有都是n个C和m个A的组合,或者是只有k个A。为了方便计算,把ACCCACCAAAC表示成A(1)C(3)A(1)C(2)A(3)C(1),这个表示可以用数组做到,然后相邻的CA中如果前面的C的个数和前面所有A的个数的和最大,那么就是最大的CA串所对应的C的个数和A的个数。但是题目中还有一个条件就是,有多个解一样长返回字典顺序大的,所以还有一个就是全是A的情况,全是A的情况只用考虑第一个表示成A()的个数。
代码:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
char word[10005],word2[10005];//数组要注意字符串有结束符
int a[505],c[505];
int main()
{
int t,t1=0;
scanf("%d",&t);
while(t--)
{
scanf("%s",word);
int i,j,count=0;
for(i=0; i<strlen(word); i++)
{
int k=0,h=0;
memset(a,0,sizeof(a));
memset(c,0,sizeof(c));
if(word[i]=='A')//遇到A就可以开始讨论它是不是ACCCACCA的需要删除的类型
{
a[k]++;
for(i++; i<strlen(word); i++) //把它们通过数组表示成A()C()的形式
{
if(word[i]=='A')
{
if(word[i-1]=='C')
h++;
a[k]++;
}
else if(word[i]=='C')
{
if(word[i-1]=='A')
k++;
c[h]++;
}
else
break;
}
for(j=k-1; j>=0; j--)//计算每个A加上后面所的A的个数
{
a[j]+=a[j+1];
}
for(j=1; j<=h; j++)//计算每个C加上后面所的C的个数
{
c[j]+=c[j-1];
}
int max=0,mark=0;
for(j=0; j<=h; j++)//找到最大CA
{
if(a[j+1]+c[j]>max)
{
max=a[j+1]+c[j];
mark=j;
}
}
if(max<=a[0])//是否是全A
{
for(j=0; j<a[0]; j++)
{
word2[count]='A';
count++;
}
}
else//如果是CA情况就把CA的中C和A的个数存入word2
{
for(j=0; j<c[mark]; j++)
{
word2[count]='C';
count++;
}
for(j=0; j<a[mark+1]; j++)
{
word2[count]='A';
count++;
}
}
word2[count]=word[i];
count++;
}
else
{
word2[count]=word[i];
count++;
}
}
word2[count]='\0';//补上结束符
printf("Case %d: %s\n",++t1,word2);
}
return 0;
}
总结:1,思维问题 2,细节问题(结束符没有考虑,wa了好几次)