hihoCoder:#1039 字符消除

1.问题描述


Time Limit:1000ms

Case Time Limit: 1000ms
Memory Limit: 256MB

Description


小Hi最近在玩一个字符消除游戏。给定一个只包含大写字母"ABC"的字符串s,消除过程是如下进行的:

1)如果s包含长度超过1的由相同字母组成的子串,那么这些子串会被同时消除,余下的子串拼成新的字符串。例如"ABCCBCCCAA"中"CC","CCC"和"AA"会被同时消除,余下"AB"和"B"拼成新的字符串"ABB"。

2)上述消除会反复一轮一轮进行,直到新的字符串不包含相邻的相同字符为止。例如”ABCCBCCCAA”经过一轮消除得到"ABB",再经过一轮消除得到"A"

游戏中的每一关小Hi都会面对一个字符串s。在消除开始前小Hi有机会在s中任意位置(第一个字符之前、最后一个字符之后以及相邻两个字符之间)插入任意一个字符('A','B'或者'C'),得到字符串t。t经过一系列消除后,小Hi的得分是消除掉的字符的总数。

请帮助小Hi计算要如何插入字符,才能获得最高得分。

Input


输入第一行是一个整数T(1<=T<=100),代表测试数据的数量。

之后T行每行一个由'A''B''C'组成的字符串s,长度不超过100。

Output


对于每一行输入的字符串,输出小Hi最高能得到的分数。

Hint


第一组数据:在"ABCBCCCAA"的第2个字符后插入'C'得到"ABCCBCCCAA",消除后得到"A",总共消除9个字符(包括插入的'C')。

第二组数据:"AAA"插入'A'得到"AAAA",消除后得到"",总共消除4个字符。

第三组数据:无论是插入字符后得到"AABC","ABBC"还是"ABCC"都最多消除2个字符。

Sample Input

3
ABCBCCCAA
AAA
ABC

Sample Output

9
4
2

2.思路分析


 这道题思路不是很难想,但需要考虑全面透彻。
 首先,我们认为程序大体分为三大部分:
1.将输入的每个字符串的各个位置都分别填充A、B、C;
         例如:输入ABC,填充后结果为:AABC,AABC,ABAC,ABCA; BABC,ABBC,ABBC,ABCB;CABC,ACBC,ABCC,ABCC;
    
2.对填充后的每一个字符串做消除,得到分数。
   
3.找出分数的最大值
             于是,我的代码是在主函数中实现第一部分;第二部分在eliminate()中实现,此函数经过探索我用了递归;第三部分在maxscore()中实现;AC。
              我的程序另外实现了找出在何位置插入什么值能得到最大得分的功能(详情请结合代码查看,解释在注释内容)。
              例如,对于输入字符串ABC,插入位置表示为:0A1B2C3。插入值表示为:A-0,B-1,C-2。
    
              代码还有很多待改进的地方,看到的朋友如有好的建议,敬请批评指正。

3.代码

#include <iostream>
#include <string>
#include <vector>
using namespace std;
typedef unsigned int size_t;
bool panduan(string &str)
{
	size_t len=str.size();
	bool flag=1;
	for(size_t i=0;i<len-1;i++)
	{
		size_t j=i+1;
		if(str[i]==str[i+1])
			flag=0;
	}
	return flag;
}

string eliminate(string &str)
{
	string newstr("");
	size_t len=str.size();
	//char pre=NULL;
	for(size_t i=0;i<len-1;)
	{
	    size_t j=i+1;
		if(str[i]!=str[j])
		{
			newstr+=str[i];
			i++;
		}
		else
		{
			while(str[i]==str[j])
			{
				++j;
			}
			i=j;
			if(j==len-1)
				newstr+=str[j];
		}
		if(i==len-2)
		{
			if(str[i]==str[i+1])
				break;
			else
				newstr+=str[i];
				newstr+=str[i+1];
				break;
		}
	}
	str=newstr;
	if(str=="")
		return str;
	if(!panduan(str))
	{
		return eliminate(str);
	}
	else
		return str;
}

vector<int> maxscore(vector<vector<int>> vec)
{
	int max=0,tmp,flagi=0,flagj=0;
	size_t len_out=vec.size();
	for(size_t i=0;i<len_out;i++ )
	{
		size_t len_in=vec[i].size();
		for(size_t j=0;j<len_in;j++)
		{
			tmp=vec[i][j];
			if(tmp>max)
			{
				max=tmp;//flagi=i;flagj=j;记录插入字母和位置
			}
		}
	}
	vector<int> arr;
	arr.push_back(max);//arr.push_back(flagi);arr.push_back(flagj);这里用向量正是为了一起返回记录的内容
	return arr;
}

int main()
{
	vector<string> str;
	int T;
	cin>>T;
	for(int i=0;i<T;i++)
	{
		string s;
		cin>>s;
		str.push_back(s);
	}
	
	string abc="ABC";
	for(int i=0;i<T;i++)
	{
		int size=str[i].size();
        vector<vector<int>> rvec;	
		for(int j=0;j<3;j++)
		{
			vector<int> score;
			for(int ins=0;ins<=size;ins++)
			{			
				string tmp=str[i];
				int len1,len2;	
				string tmp1=tmp.insert(ins,1,abc[j]);
				len1=tmp1.size();
				string tmp2=eliminate(tmp1);
				len2=tmp2.size();
				score.push_back(len1-len2);
			}
			rvec.push_back(score);
		}
		vector<int> result=maxscore(rvec);
		for(vector<int>::iterator m=result.begin();m!=result.end();m++)
		{
			cout<<*m<<" ";
		}
		cout<<endl;
	}
	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值