解题思路
这是一道字符串压缩编码问题,主要思路如下:
-
问题分析:
- 编码规则为
,表示重复
次
- 需要递归处理子串,实现嵌套编码
- 需要考虑所有可能的分割方式
- 选择能得到最短结果的编码方式
- 编码规则为
-
解决方案:
- 递归处理字符串
- 遍历所有可能的重复子串长度
- 对每个长度寻找最优的重复次数
- 将字符串分为前缀、重复部分、后缀三部分
- 递归处理这三部分
-
优化策略:
- 从最长的可能重复长度开始尝试
- 提前剪枝无效的压缩情况
- 递归处理子串实现嵌套压缩
代码
#include <bits/stdc++.h>
using namespace std;
string encoding_string(string s) {
if (s == "") return "";
if (s.size() <= 4) return s;
int len = s.size();
int len2 = len / 2; // 重复子串的最大长度
int best_count = 0; // 最优重复次数
int best_len = INT_MAX;// 最优压缩长度
string pre, cur, lat; // 前缀、重复串、后缀
while (len2 >= 1) {
for (int k = 0; k <= len - len2; k++) {
int count = 1;
string s2 = s.substr(k, len2);
// 计算重复次数
for (int j = 1; len2 * j + len2 <= len; j++) {
string s3 = s.substr(k + len2 * j, len2);
if (s2.compare(s3) == 0)
count++;
else
break;
}
// 计算压缩后长度
int newlen = (len - count * len2) + 3 + len2;
if (newlen < len && newlen < best_len && count > 1) {
best_len = newlen;
best_count = count;
pre = s.substr(0, k);
cur = s.substr(k, len2);
lat = s.substr(k + count * len2);
}
}
len2--;
}
if (best_count == 0)
return s;
// 递归处理三个部分
return encoding_string(pre) +
to_string(best_count) + "[" +
encoding_string(cur) + "]" +
encoding_string(lat);
}
int main() {
string s;
cin >> s;
cout << encoding_string(s).size() << endl;
return 0;
}
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String s = br.readLine();
br.close();
System.out.println(solution(s).length());
}
private static String solution(String s) {
if (s.length() <= 4) return s;
int len = s.length();
int rptLen = len >> 1; // 当前尝试的重复的长度
int bestRptTime = 0;
int bestCompressLen = len;
String seg1 = "", seg2 = "", seg3 = "";
while (rptLen >= 1) {
for (int k = 0; k <= len - (rptLen << 1); k++) { // 从k位置开始寻找,至少留两段
int count = 1;
String s2 = s.substring(k, k + rptLen);
for (int j = 1; k + j * rptLen + rptLen <= len; j++) { // 判断最多重复几次
String s3 = s.substring(k + j * rptLen, k + (j + 1) * rptLen);
if (s2.equals(s3)) count++;
else break;
}
int newLen = len - count * rptLen + 3 + rptLen;
if (newLen < len && newLen < bestCompressLen) { // 新长度合适
bestCompressLen = newLen;
bestRptTime = count;
seg1 = s.substring(0, k);
seg2 = s.substring(k, k + rptLen);
seg3 = s.substring(k + count * rptLen);
}
}
rptLen--;
}
if (bestRptTime == 0) return s;
return solution(seg1) + bestRptTime + "[" + solution(seg2) + "]" + solution(seg3);
}
}
def encoding_string(s: str) -> str:
if not s: return ""
if len(s) <= 4: return s
length = len(s)
len2 = length // 2
best_count = 0
best_len = float('inf')
pre = cur = lat = ""
while len2 >= 1:
for k in range(length - len2 + 1):
count = 1
s2 = s[k:k+len2]
j = 1
while len2 * j + len2 <= length:
s3 = s[k+len2*j:k+len2*j+len2]
if s2 == s3:
count += 1
else:
break
j += 1
newlen = (length - count * len2) + 3 + len2
if newlen < length and newlen < best_len and count > 1:
best_len = newlen
best_count = count
pre = s[:k]
cur = s[k:k+len2]
lat = s[k+count*len2:]
len2 -= 1
if best_count == 0:
return s
return encoding_string(pre) + \
str(best_count) + "[" + \
encoding_string(cur) + "]" + \
encoding_string(lat)
def main():
s = input().strip()
print(len(encoding_string(s)))
if __name__ == "__main__":
main()
算法及复杂度
- 算法:递归 + 贪心
- 时间复杂度:
-
为字符串长度
- 空间复杂度:
- 递归调用栈的深度