Problem 1989 AntiAC -初入算法 补题

题目:给一个只有大写字母的字符串。删除一些字母,使得结果字符串中没有“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了好几次)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值