php 数字压缩算法,压缩算法

53

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;

}

发表于 2020-03-21 11:50:44

回复(8)

19

//源代码思路参考某大神

#include 

#include 

using namespace std;

int main(){

string s;

cin>>s;

int i = 0;

while(i 

if(s[i] == ']'){

int j = i;//j用来向前寻找与]相匹配的[

int k = 0;//k用来记录'|'所在位置

while(s[j] != '['){

if(s[j] == '|')

k = j;

j--;

}

int len = stoi(s.substr(j+1,k-j));

string s1 = s.substr(k+1,i - k - 1);

string s2;

for(int si = 0; si 

s2 += s1;

}

s = s.replace(j,i-j+1,s2);

i = j;//替换后i所指向的内容变化,从替换部分的头开始再寻找

}

i++;

}

cout<

}

编辑于 2020-01-21 10:28:55

回复(9)

40

使用递归的思路非常清晰,每次解码最内层的中括号内容即可

import sys

def decode(s):

i = 0

x, y, z = -1, -1, -1

while i 

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='')

编辑于 2020-03-17 22:00:12

回复(4)

38

if __name__=='__main__':

s=input()

i=0

while(i

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)

发表于 2020-01-11 23:13:38

回复(7)

4

#include 

using namespace std;

//LeetCode解法 双栈

int main()

{

string s;

cin >> s;

stack numStk;

stack strStk;

int cnt = 0;

string ans;

for(int i = 0; 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 <

return 0;

}

发表于 2020-05-28 17:51:54

回复(0)

6

刚学正则,试写了三种语言的正则解法以体会区别:

Python:

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 

#include 

#include 

#include 

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 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 

chs += cur[2];

}

int len = cur[0].length(); // 匹配字串的长度

int pos = tmp.position(); // 匹配字串在原字串中的起始位置

line.replace(pos, len, chs);

}

cout <

} 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 

chs += m.group(2);

}

line = m.replaceFirst(chs);

m = pc.matcher(line);

}

System.out.println(line);

}

}

编辑于 2020-03-02 18:43:01

回复(5)

3

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 

str2 += splits[1];

}

str  = str.replace("[" + tmp + "]", str2);//HG[3|BCACA]F]

}

System.out.println(str);

}

}

编辑于 2020-08-20 14:53:57

回复(1)

3

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])

发表于 2020-07-02 18:05:44

回复(0)

3

//递归解决,C++

#include

using namespace std;

string decode(string str)

{

int x=-1,y=-1,z=-1;

int i=0;

while(i

{

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<

for(int j=0;j

{

num=num*10+(num_s[j]-'0');

}

//cout<

string sstr=str.substr(y+1,z-y-1);

//cout<

string ssstr="";

while(num--)

{

ssstr=ssstr+sstr;

}

//cout<

str=str.substr(0,x)+ssstr+str.substr(z+1);

//cout<

return decode(str);

}

return str;

}

int main()

{

string str;

cin>>str;

cout<

//cout<

return 0;

}

发表于 2020-04-26 00:05:32

回复(0)

3

这题考的应该是“栈”这个知识点,碰到过原题,这里给出迭代的写法,栈用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

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

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());

}

}

编辑于 2020-03-08 14:36:35

回复(1)

2

JavaScript(Node)  RegExp + slice 😎

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

mid += midStr

}

str= before+mid+after

}

console.log(str)

}

})

发表于 2020-02-18 12:30:27

回复(1)

1

让我来个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)

}

发表于 2021-02-23 00:43:15

回复(0)

1

直接用正则表达式求解,每次都去匹配“[数字|字母串]”的模式,但要注意每次进行解压替换的时候只能替换一个,否则abc[3|hb]s[5|tsq]就会把两个附和模式的地方都解压成同一个字符串的重复abchbhbhbshbhbhbhbhb,而不是abchbhbhbstsqtsqtsqtsqtsq。

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 

// 将原字符串中的重复模式替换为重复的字符串

str = m.replaceFirst(repeatStr);

// 这次匹配替换完了再按同一个模式匹配下一个子串

m = p.matcher(str);

}

System.out.println(str);

}

}

发表于 2021-02-04 10:44:15

回复(0)

1

Python版本的双栈法:

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)

编辑于 2020-11-26 19:23:44

回复(0)

1

参考top1递归的做法,十分简洁,改用javascript实现,全ac

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 

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));

编辑于 2020-08-24 11:04:53

回复(0)

1

#include 

#include 

// 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 

{

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 

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 <

return 0;

}

发表于 2020-08-20 15:15:34

回复(0)

1

//用正则

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)

}

编辑于 2020-08-20 11:33:11

回复(0)

1

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))

发表于 2020-07-03 13:47:19

回复(0)

1

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 

sb.append(x[1]);

return sb.toString();

}

// 上面if都不执行,说明既有[又有|,说明没有递归到最里层

char a[] = s.toCharArray();

// 用来存储完全解压后的字符串

StringBuffer sb = new StringBuffer();

for (int i = 0; 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();

}

}

发表于 2020-01-12 13:51:15

回复(1)

1

public static void main(String[] args) {

Scanner scanner = new Scanner(System.in);

String next = scanner.next();

scanner.close();

System.out.println(replace(next));

}

private static String replace(String str) {

if (str.contains("]")) {

int i =0;

while (i<=str.length()){

if ("]".charAt(0) == str.charAt(i++)){

break;

}

}

int j = i-1;

while (0 <= j) {

char c = str.charAt(j--);

if ("[".charAt(0) == c) {

String repeatStr = str.substring(j + 2, i - 1);

String[] split = repeatStr.split("\\|");

Integer num = Integer.parseInt(split[0]);

String compress = split[1];

StringBuilder builder = new StringBuilder();

while (0 

builder.append(compress);

num--;

}

str = replace(str.replace("["+repeatStr+"]",builder.toString()));

}

}

}

return str;

}

发表于 2020-02-07 16:42:54

回复(0)

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值