小Q想要给他的朋友发送一个神秘字符串,但是他发现字符串的过于长了,于是小Q发明了一种压缩算法对字符串中重复的部分进行了压缩,对于字符串中连续的m个相同字符串S将会压缩为[m|S](m为一个整数且1<=m<=100),例如字符串ABCABCABC将会被压缩为[3|ABC],现在小Q的同学收到了小Q发送过来的字符串,你能帮助他进行解压缩么?
输入第一行包含一个字符串s,代表压缩后的字符串。
S的长度<=1000;
S仅包含大写字母、[、]、|;
解压后的字符串长度不超过100000;
压缩递归层数不超过10层;
输出一个字符串,代表解压后的字符串。
HG[3|B[2|CA]]F
HGBCACABCACABCACAF
HG[3|B[2|CA]]F−>HG[3|BCACA]F−>HGBCACABCACABCACAF
if __name__=='__main__': s=input() i=0 while(i<len(s)): if(s[i]==']'): j=i k=0 while(s[j]!='['): if(s[j]=='|'): k=j j=j-1 s1=s[j:i+1] num=int(s[j+1:k]) sz=s[k+1:i] sz=sz*num s=s.replace(s1,sz,1) i=j i = i + 1 print(s)
#include <bits/stdc++.h> using namespace std; //LeetCode解法 双栈 int main() { string s; cin >> s; stack<int> numStk; stack<string> strStk; int cnt = 0; string ans; for(int i = 0; i < s.size(); ++i) { if(s[i] >= '0' && s[i] <= '9') { cnt = cnt * 10 + s[i] - '0'; } else if(s[i] == '|') { numStk.push(cnt); cnt = 0; } else if(s[i] == '[') { strStk.push(ans); ans.clear(); } else if(s[i] == ']') { int k = numStk.top(); numStk.pop(); while(k--) strStk.top() += ans; ans = strStk.top(); strStk.pop(); } else ans += s[i]; } cout << ans << endl; return 0; }
import re line = input() pattern = r"\[(\d+)\|(\w+)\]" tmp = re.search(pattern, line) while tmp: l, r = tmp.span()[0], tmp.span()[1] cur = line[l:r] mid = cur.find("|") num = int(cur[1:mid]) chs = cur[mid + 1:-1] * num line = line[:l] + chs + line[r:] tmp = re.search(pattern, line) print(line)Cpp:
#include <string> #include <regex> #include <iostream> #include <vector> using namespace std; int main() { string line; getline(cin, line); string pattern = "\\[(\\d+)\\|(\\w+)\\]"; regex match(pattern); smatch tmp; while (regex_search(line, tmp, match)) { vector<string> cur; for (auto iter = tmp.begin(); iter != tmp.end(); iter++) { cur.push_back(iter->str()); } int num = atoi(cur[1].c_str()); string chs = ""; // 解压的字串 for (int i = 0; i < num; i++) { chs += cur[2]; } int len = cur[0].length(); // 匹配字串的长度 int pos = tmp.position(); // 匹配字串在原字串中的起始位置 line.replace(pos, len, chs); } cout << line << endl; }Java:
import java.util.*; import java.util.regex.*; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); String line = in.next(); String pattern = "\\[(\\d+)\\|(\\w+)\\]"; Pattern pc = Pattern.compile(pattern); Matcher m = pc.matcher(line); while (m.find()) { int num = Integer.valueOf(m.group(1)); String chs = ""; for (int i = 0; i < num; i++) { chs += m.group(2); } line = m.replaceFirst(chs); m = pc.matcher(line); } System.out.println(line); } }
import java.util.*; public class Main{ public static void main(String args[]) { Scanner scan = new Scanner(System.in); String str = scan.next(); while(str.contains("]")) { int right = str.indexOf("]"); int left = str.lastIndexOf("[",right); String tmp = str.substring(left+1,right); // 2|CA String[] splits = tmp.split("\\|"); int n = Integer.parseInt(splits[0]); String str2 = ""; for(int i = 0; i < n;i++) { str2 += splits[1]; } str = str.replace("[" + tmp + "]", str2);//HG[3|BCACA]F] } System.out.println(str); } }
s=input() substr=[""] repnum=[""] n=0 for i in range(0,len(s)): if s[i]>='A' and s[i]<='Z': substr[n]+=s[i] elif s[i]>='0' and s[i]<='9': repnum[n]+=s[i] elif s[i]=="[": substr.append("") repnum.append("") n+=1 elif s[i]=="]": S=substr.pop() m=repnum.pop() n-=1 substr[n]+=S*int(m) print(substr[0])
//递归解决,C++ #include<bits/stdc++.h> using namespace std; string decode(string str) { int x=-1,y=-1,z=-1; int i=0; while(i<str.size()) { if(str[i]=='[') { x=i; } if(str[i]=='|') { y=i; } if(str[i]==']') { z=i; break; } i++; } if (x!=-1&&y!=-1&&z!=-1) { int num=0; string num_s=str.substr(x+1,y-x-1); //cout<<num_s<<endl; for(int j=0;j<num_s.size();j++) { num=num*10+(num_s[j]-'0'); } //cout<<num<<endl; string sstr=str.substr(y+1,z-y-1); //cout<<sstr<<endl; string ssstr=""; while(num--) { ssstr=ssstr+sstr; } //cout<<ssstr<<endl; str=str.substr(0,x)+ssstr+str.substr(z+1); //cout<<str<<endl; return decode(str); } return str; } int main() { string str; cin>>str; cout<<decode(str); //cout<<str; return 0; }
这题考的应该是“栈”这个知识点,碰到过原题,这里给出迭代的写法,栈用LinkedList实现
stack_res用于暂时保存在 ' ] ' 之前记录的结果,保存的形式如[HG],[B],[CA]
mutil_stack保存的是数字,如[3],[2]
在遇到 ' ] ' 时, 从mutil_stack 队尾取出数字N,对当前字符串[CA] 复制N次。并从stack_res取出上一轮暂存的结果[B]拼接[CA CA]-->[B CACA]
import java.util.LinkedList; import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner in =new Scanner(System.in); String str=in.nextLine(); int mutil=0;//乘数 LinkedList stack_res=new LinkedList();//结果暂存 LinkedList mutil_stack=new LinkedList(); StringBuilder temp=new StringBuilder(); for(int i=0;i<str.length();i++) { //toCharArray() 需要O(n)的空间复杂度,不打算使用 if(str.charAt(i)=='[') { stack_res.addLast(temp.toString());//保存上一次的结果 [HG] temp=new StringBuilder();//用于接收新的字母[B] }else if(str.charAt(i)==']') { StringBuilder temp2=new StringBuilder(); //取出乘数 int num= mutil_stack.removeLast(); for(int j=0;j<num;j++) { temp2.append(temp); } temp=new StringBuilder(stack_res.removeLast()+temp2); }else if(str.charAt(i)=='|') {//乘数[3]入栈 mutil_stack.addLast(mutil); mutil=0;//寻找新的乘数比如[2] } else if(str.charAt(i)>='0'&&str.charAt(i)<='9') { //预防数字出现 [ 19 |a] mutil=mutil*10+Integer.parseInt(str.charAt(i)+""); }else { //正常字母 temp.append(str.charAt(i)); } } System.out.print(temp.toString()); } }
const readline = require('readline') const rl = readline.createInterface({ input: process.stdin, ouput: process.stdout }) let inArr = [] rl.on('line', line=>{ if(!line) return inArr.push(line.trim()) if(inArr.length === 1){ const reg1 = /\[\d+\|[A-Z]*\]/ //[num/(A-Z)*] const reg2 = /\|/ // | let str = inArr[0] //inArr str while(true){ let res = reg1.exec(str) if(!res) { break } let index = res.index let before = str.slice(0,index) let midIndex = reg2.exec(res[0]).index+index let midNum = str.slice(index+1, midIndex) let midStr = str.slice(midIndex+1,index+res[0].length-1) let after = str.slice(index+res[0].length) let mid = '' for(let i = 0;i<midNum;i++){ mid += midStr } str= before+mid+after } console.log(str) } })
#include <iostream> using namespace std; string ans,str; int pos; int get_num() { int num = 0; while(str[pos] >= 48 && str[pos] <= 57) { num *= 10; num += str[pos] - '0'; pos++; } return num; } bool is_it(char ch) { if(ch >= 65 && ch <= 90) return true; return false; } string get_str() { int num = get_num(); pos++; string temp = ""; string ans_temp = ""; while(str[pos] != ']') { if(is_it(str[pos])){ temp += str[pos]; pos++; } if(str[pos] == '[') { pos++; temp += get_str(); } } pos++; //cout<<num<<endl; for(int i=0;i<num;i++) ans_temp += temp; //cout<<ans_temp<<endl; return ans_temp; } int main() { cin>>str; //cout<<str<<endl; ans = ""; pos = 0; for(;pos<str.size();) { if(is_it(str[pos])){ ans += str[pos]; pos++; } if(str[pos] == '[') { pos++; ans += get_str(); } } cout<<ans<<endl; return 0; }使用递归
让我来个go语言 package main import ( "fmt" "strings" ) func find(s string) (int, int) { j := 0 for j < len(s) && s[j] != ']' { j++ } i := j - 1 for i >= 0 && s[i] != '[' { i-- } return i, j } func main() { var s string fmt.Scanln(&s) ans := "" for { x, y := find(s) // 找到匹配的[]的位置 if x == -1 && y == len(s) { break } num := 0 k := x + 1 for s[k] != '|' { num *= 10 num += int(s[k] - '0') k++ } //计算重复数字 ans = s[:x] + strings.Repeat(s[k + 1:y], num) + s[y + 1:] s = ans //更新s } fmt.Println(s) }
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; import java.util.regex.*; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String str = br.readLine().trim(); // 构建正则表达式模式:压缩后应该为[数字|字母字符串] String pattern = "\\[(\\d+)\\|(\\w+)\\]"; Pattern p = Pattern.compile(pattern); // 按模式pattern对str进行匹配 Matcher m = p.matcher(str); while(m.find()){ // 模式中第一个括号里的东西 int count = Integer.parseInt(m.group(1)); // 字母字符串的重复次数 // 模式中第二个字符串里的东西 String mode = m.group(2); // 重复的字符串 // 解压 String repeatStr = ""; for(int i = 0; i < count; i++) repeatStr += mode; // 将原字符串中的重复模式替换为重复的字符串 str = m.replaceFirst(repeatStr); // 这次匹配替换完了再按同一个模式匹配下一个子串 m = p.matcher(str); } System.out.println(str); } }
s = input() numStk, strStk = [], [] ans = "" cnt = 0 for i in range(len(s)): if s[i].isdigit(): cnt = cnt * 10 + int(s[i]) elif s[i] == '[': strStk.append(ans) ans = "" elif s[i] == '|': numStk.append(cnt) cnt = 0 elif s[i] == ']': k = numStk.pop() tmp = strStk.pop() for _ in range(k): tmp += ans ans = tmp else: ans += s[i] print(ans)
let line = readline() function decode(s) { let i =0; let x = -1, y = -1, z = -1; let times = 0; let sub = ""; let decodeStr = ""; while(i < s.length){ if(s[i] === '['){ x = i; } else if (s[i] === '|'){ y = i; } else if (s[i] === ']'){ z = i; break; } i++; } if(x !== -1 && y !== -1 && z !== -1){ times = parseInt(s.slice(x + 1, y)); //console.log("times:", times); sub = s.slice(y + 1, z); //console.log("sub:", sub); decodeStr = s.slice(0, x) + sub.repeat(times) + s.slice(z + 1); //console.log("decodeStr:", decodeStr); return decode(decodeStr); } return s; } console.log(decode(line));
#include <string> #include <iostream> // c++ 5 ms python 135ms // 思路参考大神 using namespace std; string decode(const string& str) { int i = 0; int x = -1, y = -1, z = -1; while (i < str.size()) { if (str[i] == '[') x = i; else if (str[i] == '|') y = i; else if (str[i] == ']') { z = i; break; } i += 1; } if (x != -1 && y != -1 && z != -1) { int times = atoi(str.substr(x+1, y-x-1).c_str()); string sub = str.substr(y+1, z-y-1); auto subs = [=]() {string tmp; for (int i = 0; i < times; i++) {tmp += sub;} return tmp;}; string decode_str = str.substr(0, x) + subs() + str.substr(z+1); return decode(decode_str); } return str; // 如果一个中括号都没有,说明没有需要解码的部分 } int main() { string str; while (cin >> str) cout << decode(str) << endl; return 0; }
//用正则 var a = readline(); fn(a); function fn(str) { var reg = new RegExp(/\[[^\[\]]*?\]/g); var arr = reg.exec(str); while (arr != null) { let tmp = arr[0]; let record = arr[0]; tmp = tmp.split(''); tmp.pop(); tmp.shift(); tmp = tmp.join('') tmp = tmp.split('|'); let temp = tmp[1].repeat(Number(tmp[0])); str = str.replace(record, temp); var reg = new RegExp(/\[[^\[\]]*?\]/g); var arr = reg.exec(str); } console.log(str) }
import sys while True: line = sys.stdin.readline().strip() if line == "": break stack = [] for s in line: if s != ']': stack.append(s) else: temp = '' while stack and stack[-1] != '|': temp = stack.pop() + temp stack.pop() times = '' while stack and stack[-1].isdigit() and stack[-1] != '[': times = stack.pop() + times stack.pop() stack.append(int(times) * temp) print("".join(stack))
import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner sc = new Scanner(System.in); String s = sc.nextLine(); System.out.println(tar(s)); } // 递归方法 public static String tar(String s) { // 递归结束的判断,说明全部解压完毕 if (!s.contains("[") && !s.contains("|")) { return s; } // 形如2|cd的变成cdcd if (!s.contains("[") && s.contains("|")) { String x[] = s.split("\\|"); int num = Integer.parseInt(x[0]); StringBuffer sb = new StringBuffer(); for (int i = 0; i < num; i++) sb.append(x[1]); return sb.toString(); } // 上面if都不执行,说明既有[又有|,说明没有递归到最里层 char a[] = s.toCharArray(); // 用来存储完全解压后的字符串 StringBuffer sb = new StringBuffer(); for (int i = 0; i < a.length; i++) { // 设置栅栏,使得"["与"]"的个数相同,比如HG[3|B[2|CA]]F,会取得[3|B[2|CA]] int latch = 0; if (a[i] == '[') { latch++; // 指针往前进一位,形如[3|B[2|CA]],需要得到3|B[2|CA],为了去掉最外面的括号 i++; if (a[i] == ']') { latch--; } // 用来存储部分解压的字符串,比如有字符串HG[3|B[2|CA]]F中的,这次while循环结束 s1会变成3|B[2|CA] // 这里再次进行'['的判断是存在[[]]的情况 StringBuffer s1 = new StringBuffer(); while (!(a[i] == ']' && latch == 0)) { if (a[i] == '[') { latch++; } if (a[i] == ']') { latch--; if (latch == 0) { // 说明到了最外层的]了,不进行下面的appen,为了取出最外层的[] continue; } } s1.append(a[i]); // 指针后移,再次进入while循环 i++; } // 如果有初始字符串HG[3|B[2|CA]]F,此时s1为3|B[2|CA],去除了一层括号, String s2 = tar(s1.toString()); // 判断里面还有没有未解压的字符串,有就继续解压,会递归到最里面的2|CA,得到CACA,返回到s2=3|BCACA,再次进行解压 while (s2.contains("|")) { s2 = tar(s2); } // 将解压完毕的字符串字符串加到sb后面 sb.append(s2); } else { // 如果没有进行压缩的字符串,直接加到末尾就行 sb.append(a[i]); } } return sb.toString(); } }
#include"stdio.h" #include"string" #include<iostream> #include<stack> #include<vector> using namespace std; int end1=0; string s2(string s){ stack<char> st; for(int i=0;i<s.length();i++){ if(s[i]=='['){ st.push(s[i]); } else if(s[i]==']'){ char tmpc=st.top(); string tmp; while(tmpc>='A' && tmpc<='Z'){ tmp=tmpc+tmp; st.pop(); tmpc=st.top(); } if(!st.empty()){//delete '|' st.pop(); } int n=0; int cntn=1; while(st.top()>='0' && st.top()<='9'){ n=n+(st.top()-'0')*cntn; st.pop(); cntn*=10; } string to_store; while(n>0){ to_store+=tmp; n--; } if(!st.empty()){//delete '[' st.pop(); } for(char tmpc:to_store){ st.push(tmpc); } } else{ st.push(s[i]); } } string res; while(!st.empty()){ res=st.top()+res; st.pop(); } return res; } int main(){ string str; cin>>str; string res=s2(str); cout<<res<<endl; return 0; }
public static void main(String[] args) { Scanner scanner = new Scanner(System.in); String next = scanner.next(); scanner.close(); System.out.println(decode(next)); } public static String decode(String words){ while (words.contains("]")){ int right = words.indexOf("]"); int left = words.lastIndexOf("[", right); String repeatStr = words.substring(left+1, right); String[] split = repeatStr.split("\\|"); words = words.replace("["+repeatStr+"]", String.join("", Collections.nCopies(Integer.parseInt(split[0]), split[1]))); } return words; }
import sys def decode(s): i = 0 x, y, z = -1, -1, -1 while i < len(s): if s[i] == '[': x = i elif s[i] == '|': y = i elif s[i] == ']': z = i break i += 1 if x != -1 and y != -1 and z != -1: times = int(s[x + 1:y]) # 次数 sub = s[y + 1:z] # 子串 decode_str = s[:x] + times * sub + s[z + 1:] # 解码 return decode(decode_str) # 递归解码 return s # 如果一个中括号都没有,说明没有需要解码的部分 for s in sys.stdin: print(decode(s), end='')