猿辅导:字符压缩算法(括号匹配)
题目描述
猿辅导APP需要下发一些宣传文本给学生,工程师们使用了一种字符压缩算法,为了简单起见,假设被压缩的字符全部为大写字母序列,A,B,C,D,E……Z,压缩规则如下:
1. AAAB 可以压缩为 A3B(单字符压缩不加括号)
2. ABABA 可以压缩为 (AB)2A (多字符串压缩才加括号)
输入数据保证不会出现冗余括号,且表示重复的数字一定合法且大于1,即不会出现:
- (A)2B ---------(应为:A2B)
- ((AB))2C ---------(应为:(AB)2C)
- (A)B ---------(应为:AB)
- A1B ---------(应为:AB)
注意:数字可能出现多位数即 A11B 或者 (AB)10C 或者 A02这种情况
A11B = AAAAAAAAAAAB
(AB)10C = ABABABABABABABABABABC
A02 = AA
数据分布:
对于60%的数据,括号不会出现嵌套,即不会有((AB)2C)2 这种结构。
对于80%的数据,括号最多嵌套1层-,不会有(((AB)2C)2D)99这种结构。
对于100%的数据,括号可以嵌套任意层
输入描述:
第一行是正整数C(C<=100),表示下面有C组数据。
之后C行,每一行为一组数据,每组数据为一个字符串。
每个字符串由A-Z,0-9,(,),组成表示一个压缩后的串,保证输入数据一定合法且字符串长度小于50
5
A11B
(AA)2A
((A2B)2)2G
(YUANFUDAO)2JIAYOU
A2BC4D2
输出描述:
输出C行,每行读音一个数据的输出结果,表示压缩前的字符串,保证每个字符串展开的长度不超过10^6.
AAAAAAAAAAAB
AAAAA
AABAABAABAABG
YUANFUDAOYUANFUDAOJIAYOU
AABCCCCDD
分析
括号匹配,用栈来实现
代码
import java.util.Scanner; import java.util.Stack; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int C=sc.nextInt();//字符串数目 sc.nextLine(); String[] str = new String[C];//保存字符串 for (int i = 0; i < C; i++) { str[i] = sc.nextLine(); } for (int i = 0; i < C; i++) { String results = decompressChar(str[i]); System.out.println(results); } } /** * 将字符串解压缩 * @param str * @return */ public static String decompressChar(String str) { StringBuilder sb = new StringBuilder(""); StringBuilder tmp = new StringBuilder(""); char flag = '('; Stack<Character> stack = new Stack<Character>(); char[] chars = str.toCharArray();//将压缩后的字符串转为字符数组 int count = 0;//用于保存字符串重复的次数 //遍历每个数组将其放入栈中 for (int i = 0; i < chars.length; i++) { /**获取字符串需要重复的次数*/ while(i < chars.length && (chars[i] + "").matches("[0-9]")){ count = count * 10 + Integer.parseInt(chars[i] + ""); i++; } /**解压字符串并放入栈中*/ count = putUnCompressedValueToStack(count, tmp, stack); if(i == chars.length){break;}//如果数字字符位于字符串末尾,直接跳出 /**如果是 ( 直接放入栈中*/ if (chars[i] =='(') { stack.push(chars[i]); /**如果是 ) 从栈中获取需要重复的字符子串,并将)移除栈*/ }else if (chars[i] ==')') { tmp = getStackValue(stack, flag); stack.pop(); /**如果是字母*/ }else if((chars[i] + "").matches("[A-Z]")) { // 如果是单个字母重复,获取单个字母 if(i < (chars.length-1) && (chars[i+1] + "").matches("[0-9]")){ tmp = new StringBuilder("").append(chars[i]); // 字母不重复,直接入栈 }else{ stack.push(chars[i]); } } } /**获取栈中所有的字符串*/ sb = getStackValue(stack, flag); /**注意栈先进先出,需要逆转字符串*/ return sb.reverse().toString(); } /** * 获得栈中的元素,直到值与character相等 * @param stack 栈 * @param character 某个字符 * @return */ public static StringBuilder getStackValue(Stack<Character> stack, Character character){ StringBuilder tmp = new StringBuilder(""); while(!stack.isEmpty() && stack.peek()!= character){ tmp.append(stack.peek()); stack.pop(); } return tmp; } /** * 解压字符串并放入栈中 * @param count tmp重复的次数 * @param tmp 需要重复的字符串 * @param stack 栈 * @return */ public static int putUnCompressedValueToStack(int count,StringBuilder tmp, Stack<Character> stack){ if(count>0 && tmp.length()!=0){ for (int j = 0; j < count; j++) { for (int k = tmp.length()-1; k>=0; k--) { stack.push(tmp.charAt(k)); } } } return 0; } }