#hihocoder #1039 字符消除

来源:互联网 发布:config.inc.php 编辑:程序博客网 时间:2024/04/30 03:00

  总结自己的代码能力,就是渣渣渣。找工作,看到各路大神高歌猛进,自己却…因此痛定思痛,困而学之,决定悔改自新,从头来过…

题目:#1039 : 字符消除

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

  1. 如果s包含长度超过1的由相同字母组成的子串,那么这些子 串会被同时消除,余下的子串拼成新的字符串。例如”ABCCBCCC AA”中”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

  这道题目比较简单直接,主要考察对于字符的操作,需要依次遍历原字符串每个位置(共n+1个位置,假设字符串长度为n)分别添加‘A’,‘B’,‘C’的情况,一共有3*(n+1)种情况。然后对每种情况的字符串做处理。
依次判断相邻字符是否相等,设置一个计数变量。对于相等的情况,一开始的想法是对原字符串相应位置重置为一个不会出现的字符,比如‘D’,然后下一步再将其去除,递归处理新产生的字符串。对于新字符串长度为1,或者新旧字符串长度没有变化的,停止递归。

import java.util.Scanner;public class Main {    private static void earse(String input) {        int res = 0;        int max = 0;        char[] cArray = new char[input.length() + 1];        char[] change = {'A', 'B', 'C'};        for (int k = 0; k < 3; k++) {            for (int i = 0; i < input.length() + 1; i++) {                cArray[i] = change[k];                for (int j = 0; j < i; j++) {                    cArray[j] = input.charAt(j);                }                for (int j = i + 1; j < input.length() + 1; j++) {                    cArray[j] = input.charAt(j-1);                }                res = earse(cArray);                if (res > max) {                    max = res;                }            }        }        System.out.println(max);    }    private static int earse(char[] cArray) {        if (cArray.length <= 1) {            return 0;        }        int res = 0;        for (int i = 0; i < cArray.length; i++) {            int cnt = 1;            while (i < cArray.length - 1 && cArray[i+1] == cArray[i]) {                i++;                cnt++;            }            res += (cnt != 1 ? cnt : 0);            if (cnt != 1) {                for (int j = i + 1 - cnt; j <= i; j++) {                    cArray[j] = 'D';                }            }        }        if (String.valueOf(cArray).matches(".*D.*") && cArray.length - res >= 2) {            char[] nChar = new char[cArray.length - res];            int j = 0;            for (int i = 0; i < cArray.length; i++) {                if (cArray[i] != 'D') {                    nChar[j++] = cArray[i];                }            }            return res + earse(nChar);        } else {            return res;        }    }    public static void main(String[] args) {        Scanner sin = new Scanner(System.in);        int N = sin.nextInt();         while(N-- != 0){            String P = sin.next();            earse(P);        }    }}

  由于有对字符的操作,一开始使用了char数组,操作比较繁琐,后来考虑使用了String类,题目中对String的拼接较多,因此使用了Stringbuilder类。本来StringBuilder的操作比char数组慢一些,但是char数组什么需要提前定义大小,因此中间多了一步关于‘D’的操作,总体速度反而满了。

import java.util.Scanner;public class Main {    private static void earse(StringBuilder input) {        int res = 0;        int max = 0;        StringBuilder cArray = new StringBuilder();         char[] change = {'A', 'B', 'C'};        for (int k = 0; k < 3; k++) {            for (int i = 0; i < input.length() + 1; i++) {                if (i == 0) {                    cArray.append(change[k]).append(input);                } else if (i == input.length()) {                    cArray.append(input).append(change[k]);                } else {                    cArray.append(input.subSequence(0, i))                    .append(change[k]).                    append(input.subSequence(i, input.length()));                }                res = earse2(cArray);                if (res > max) {                    max = res;                }                cArray.delete(0, cArray.length());            }        }        System.out.println(max);    }    private static int earse2(StringBuilder cArray) {        if (cArray.length() <= 1) {            return 0;        }        int res = 0;        StringBuilder nChar = new StringBuilder();        for (int i = 0; i < cArray.length(); i++) {            int cnt = 1;            while (i < cArray.length() - 1 && cArray.charAt(i+1) == cArray.charAt(i)) {                i++;                cnt++;            }            if (cnt == 1) {                // 使用正向添加,不是反向删除,速度略有加快                nChar.append(cArray.charAt(i));             } else {                res += cnt;               }        }        if (cArray.length() - nChar.length() > 0             && nChar.length() >= 2) {            return res + earse2(nChar);        } else {            return res;        }    }    public static void main(String[] args) {        Scanner sin = new Scanner(System.in);        int N = sin.nextInt();         while(N-- != 0){            String P = sin.next();            earse(new StringBuilder(P));        }    }}

  微末道行,暂时就这样了,有时间再多修改自己的代码。过阵子回头来看自己,觉得自己当初怎么这么渣就对了,表面那是功力比现在好…

Java中的知识点:
1.String类与StringBuilder类的区别

  • 对String对象的任何改变都不影响到原对象,相关的任何change操作都会生成新的对象
  • String str=”hello world”和String str=new String(“hello world”)的区别(是否产生新的对象)
  • String、StringBuffer以及StringBuilder的区别(是否产生新的字符串、线程安全)

2.char数组与String类的区别

0 0
原创粉丝点击