题目链接:http://hihocoder.com/problemset/problem/1039

题意:给定一个只由{A, B, C}组成的字符串s,长度为n, 故包含n+1个空隙;现要求在某个空隙插入一个来自{A, B, C}的字符,然后按照以下“消除规则”对插入后的字符串进行消除操作,问最多能消掉几个字符(包含插入的一个)。

  消除规则:

  1. 自左至右扫描当前字符串,若字符v从某个位置开始连续出现了2次及以上,则此区间内的v全部消除;

  2. 重复步骤1直至不再有可消除的字符。

思路:模拟,枚举。

  这个题有点像之前数据结构编程作业的“祖玛”一题,同样是会产生连锁反应的“消除规则”,不过那道题是给定一个方案,包含一连串的插入操作,直接用动态链表模拟就好。而这道题要求最佳方案,所以可以枚举所有可能的插入方案,对每个方案都要模拟出消除后的结果。动态申请内存显然不合适,而节点数又固定为n+1,所以我用静态链表来实现。

有两个值得注意的地方:

1. 之前以为可以这样剪枝:在挑选每个位置插入的字符时,只考虑和相邻字符相同的。然而一直WA。。。感谢这篇题解给出的反例 BBBAB http://blog.csdn.net/Lu597203933/article/details/44245411

2. 关于复杂度分析:开始时不敢枚举,总感觉是指数的复杂度,但听了Kirai同学的聚合分析后明白了。简述如下:

  (1)首先有n+1个空隙,每个空隙有3种选择,故共有3*(n+1)种插入方案;

  (2)其次对于每个插入方案,要经历若干趟扫描,而停止扫描的标志为上一趟扫描是否发生过消除;

  具体地,设第 i 趟扫描前字符串长度为 m ,由于一趟扫描过程中指针不回溯,所以一趟扫描花费的时间为线性的,记为t[i] = T(m)。若此趟发生了消除,则字符串的长度必然至少减1,故t[i+1] <= T(m-1)。而初始字符串长度为n+1,故至多经过n趟扫描后,必然达到最终状态。

  至此观察所有趟扫描的时间花费序列t,从t[n]到t[1],呈算术级数,故求和后与末项平方同阶,为T(n2)。

  (3)总的时间复杂度为O(n2 * 3 * (n+1)) = O(n3)

关于代码:Debug的时间太长了,需要多写些模拟题

 #include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#define REP(N) for(int i=0; i<(N); i++)
#define REPE(N) for(int i=1; i<=(N); i++)
#define CLEAR(A, X) memset(A, X, sizeof(A))
#define FREAD(FN) freopen((FN), "r", stdin)
#define pb(a) push_back(a)
#define SINT(X) scanf("%d", &(X))
using namespace std;
const int MAX_C = ; struct Node
{
char c;
int next;
}nodes[MAX_C];//静态链表
int n;//节点个数
int head; int T;
char s[MAX_C];
int ans; void reset(){//重置为原始序列
n = ;
for(int i = ; s[i] != '\0'; i++){//[1, n]
nodes[i].next = i+;//来自前驱的引用
nodes[i+].c = s[i];//[0]为头结点
n++;
}
nodes[n].next = -;//末元的后继
} int main()
{
FREAD("1039.txt");
head = ;
SINT(T);
while(T--){
scanf("%s", s);
ans = ;
reset();//初始化原始序列
for(char t = 'A'; t <= 'C'; t++){
nodes[n+].c = t;//待插入的元素统一放在[n+1]
for(int i=; i<=n; i++){//插在i与i+1之间
// if(nodes[i].c != t && nodes[i+1].c != t) continue;//这里不能剪枝!!BBBAB这个可以在第一个B后插入一个A而全部消掉
//printf("insert %c after index %d\n", t, i);
nodes[n+].next = nodes[i].next;
nodes[i].next = n + ;
int cnt = ;
bool updated = ;//这趟扫描是否发生了消除
head = ;
// printf("before disappear\n");
// for(int j = nodes[head].next; j != -1; j = nodes[j].next){
// printf("%c", nodes[j].c);
// }
// printf("\n");
while(updated){//这趟扫描没有发生消除,则退出
updated = ;
int discovered = ;
int pre = head;//cur的前驱
int cur = nodes[head].next;
while(cur != - && nodes[cur].next != -){//一趟自左到右的扫描
int j = nodes[cur].next;
//printf("%c %c\n", nodes[cur].c, nodes[j].c);
while(j != - && nodes[j].c == nodes[cur].c){
updated = ;//发现可消
discovered = ;//发现了以cur为开始可消串
cnt++;
//printf("delete %c\n", nodes[j].c);
nodes[cur].next = nodes[j].next;//删除j
j = nodes[j].next;
}
if(discovered){//发现连续的cur,可消
cnt++;//加上开头的cur
discovered = ;
nodes[pre].next = nodes[cur].next;//删除cur
cur = nodes[pre].next;//新的起点
}else{//未发现,cur只有一个
pre = cur;
cur = nodes[cur].next;
}
// printf("delete one cluster\n");
// for(int j = nodes[head].next; j != -1; j = nodes[j].next){
// printf("%c", nodes[j].c);
// }
// printf("\n");
}
// printf("disappear once\n");
// for(int j = nodes[head].next; j != -1; j = nodes[j].next){
// printf("%c", nodes[j].c);
// }
// printf("\n");
}
nodes[i].next = nodes[n+].next;//删除插入的[n+1]
ans = max(ans, cnt);
//printf("ans this %d\n", cnt);
reset();
}
}
printf("%d\n", ans);
}
return ;
}

【hihocoder 1039 字符串消除】模拟的更多相关文章

  1. hihoCoder 1039:字符消除(字符串处理)

    #1039 : 字符消除 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi最近在玩一个字符消除游戏.给定一个只包含大写字母"ABC"的字符串s,消 ...

  2. hihocoder #1039 : 字符消除 ( 字符串处理类 ) 好久之前做的题目,具体的算法代码中阅读吧

    #1039 : 字符消除 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi最近在玩一个字符消除游戏.给定一个只包含大写字母"ABC"的字符串s,消 ...

  3. hihoCoder 1039字符消除 (字符串处理)

    http://hihocoder.com/problemset/problem/1039 因为字符串只由3种字母组成,并且插入的字符也只能是这三种字符的其中一个,那么可以考虑枚举这三个字符其中一个字符 ...

  4. [hihoCoder]#1039 : 字符消除

    Description 小Hi最近在玩一个字符消除游戏.给定一个只包含大写字母"ABC"的字符串s,消除过程是如下进行的: 1)如果s包含长度超过1的由相同字母组成的子串,那么这些 ...

  5. hihoCoder 1039 字符消除 最详细的解题报告

    题目来源:字符消除 解题思路: 1.在给定字符串中的任意位置插入'A'.'B'.'C'中的任意一个字符,然后计算插入后的字符经过消除后最短的字符串长度: 2.在计算字符消除后最短长度时,智能一遍一遍的 ...

  6. 【hihoCoder】#1039 : 字符消除 by C solution

    #1039 : 字符消除 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi最近在玩一个字符消除游戏.给定一个只包含大写字母"ABC"的字符串s,消 ...

  7. ACdream 1188 Read Phone Number (字符串大模拟)

    Read Phone Number Time Limit:1000MS     Memory Limit:64000KB     64bit IO Format:%lld & %llu Sub ...

  8. 【hihoCoder】1039 : 字符消除

    题目:http://hihocoder.com/problemset/problem/1039 给定一个字符串s,只包含'A', 'B', 'C'三种字符 1. 向 s 的任意位置 (包括头和尾) 中 ...

  9. 【HIHOCODER 1039】 字符消除

    链接 问题描述 小Hi最近在玩一个字符消除游戏.给定一个只包含大写字母"ABC"的字符串s,消除过程是如下进行的: 1)如果s包含长度超过1的由相同字母组成的子串,那么这些子串会被 ...

随机推荐

  1. 第26讲 对话框AlertDialog的自定义实现

    第26讲对话框AlertDialog的自定义实现 比如我们在开发过长当中,要通过介绍系统发送的一个广播弹出一个dialog.但是dialog必需是基于activity才能呈现出来,如果没有activi ...

  2. 如何安装CocoaPods

    转自 http://www.99css.com/1321/ 在 iOS 项目开发中,经常会用到第三方的源代码,CocoaPods 就是为了方便管理这些源码的工具. 在官方教程里面,安装看起来非常简单 ...

  3. AIX下RAC搭建 Oracle10G(一)检測系统环境

    AIX下RAC搭建系列 环境 节点 节点1 节点2 小机型号 IBM P-series 630 IBM P-series 630 主机名 AIX203 AIX204 交换机 SAN光纤交换机 存储 S ...

  4. Grizzly开发Echoserver实战

    Grizzly开发Echoserver实战 作者:chszs,转载需注明. 博客主页:http://blog.csdn.net/chszs 用Java编写可伸缩的server应用是有难度的.用Java ...

  5. 把自己的程序打成jar包,让别人调用

     我们写程序的时候往往需要把自己的程序打包成jar包,给第三方调用.Eclipse让我们非常方便的可以导出jar包.但是当程序里需要用到res里的资源时,往往就会出现问题.因为统自动生成的R类如果被打 ...

  6. [Android算法] bitmap 将图片压缩到指定的大小

    Bitmap压缩到指定大小: private void imageZoom() {//图片允许最大空间 单位:KBdouble maxSize =400.00;//将bitmap放至数组中,意在bit ...

  7. JavaScript 中的事件设计

    1. 事件绑定的几种方式  主要介绍一下 最常用的事件设计 其他就稍微带过. 直接在代码里面添加onclick指定函数名字. B) 在JS代码中通过dom元素的onclick等属性 这种做法this表 ...

  8. python - 面向对象(一)

    python是一门面向对象的编程语言,python中的一切均是对象. 有对象就提到类,对象和类就像是儿子和老子的关系,是不可分的一对. 什么是类     类就是具有一些共同特性的事物的统称.好比人类, ...

  9. (转)javascript深入理解js闭包

    一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...

  10. nyoj 最少步数

    算法:搜索(深度优先搜索) 描述 这有一个迷宫,有0~8行和0~8列: 1,1,1,1,1,1,1,1,1 1,0,0,1,0,0,1,0,1 1,0,0,1,1,0,0,0,1 1,0,1,0,1, ...