Given a non-empty string, encode the string such that its encoded length is the shortest.

The encoding rule is: k[encoded_string], where the encoded_string inside the square brackets is being repeated exactly k times.

Note:

  1. k will be a positive integer and encoded string will not be empty or have extra space.
  2. You may assume that the input string contains only lowercase English letters. The string's length is at most 160.
  3. If an encoding process does not make the string shorter, then do not
    encode it. If there are several solutions, return any of them is fine.

Example 1:

Input: "aaa"
Output: "aaa"
Explanation: There is no way to encode it such that it is shorter than the input string, so we do not encode it.

Example 2:

Input: "aaaaa"
Output: "5[a]"
Explanation: "5[a]" is shorter than "aaaaa" by 1 character.

Example 3:

Input: "aaaaaaaaaa"
Output: "10[a]"
Explanation: "a9[a]" or "9[a]a" are also valid solutions, both of them have the same length = 5, which is the same as "10[a]".

Example 4:

Input: "aabcaabcd"
Output: "2[aabc]d"
Explanation: "aabc" occurs twice, so one answer can be "2[aabc]d".

Example 5:

Input: "abbbabbbcabbbabbbc"
Output: "2[2[abbb]c]"
Explanation: "abbbabbbc" occurs twice, but "abbbabbbc" can also be encoded to "2[abbb]c", so one answer can be "2[2[abbb]c]".
 
这道题让我们压缩字符串,把相同的字符串用中括号括起来,然后在前面加上出现的次数,感觉还是一道相当有难度的题呢。参考了网上大神的帖子才弄懂该怎么做,这道题还是应该用DP来做。我们建立一个二维的DP数组,其中dp[i][j]表示s在[i, j]范围内的字符串的缩写形式(如果缩写形式长度大于子字符串,那么还是保留子字符串),那么如果s字符串的长度是n,最终我们需要的结果就保存在dp[0][n-1]中,然后我们需要遍历s的所有子字符串,对于任意一段子字符串[i, j],我们\\我们以中间任意位置k来拆分成两段,比较dp[i][k]加上dp[k+1][j]的总长度和dp[i][j]的长度,将长度较小的字符串赋给dp[i][j],然后我们要做的就是在s中取出[i, j]范围内的子字符串t进行合并。合并的方法是我们在取出的字符串t后面再加上一个t,然后在这里面寻找子字符串t的第二个起始位置,如果第二个起始位置小于t的长度的话,说明t包含重复字符串,举个例子吧,比如 t = "abab", 那么t+t = "abababab",我们在里面找第二个t出现的位置为2,小于t的长度4,说明t中有重复出现,重复的个数为t.size()/pos = 2个,那么我们就要把重复的地方放入中括号中,注意中括号里不能直接放这个子字符串,而是应该从dp中取出对应位置的字符串,因为重复的部分有可能已经写成缩写形式了,比如题目中的例子5。再看一个例子,如果t = "abc",那么t+t = "abcabc",我们在里面找第二个t出现的位置为3,等于t的长度3,说明t中没有重复出现,那么replace就还是t。然后我们比较我们得到的replace和dp[i][j]中的字符串长度,把长度较小的赋给dp[i][j]即可,时间复杂度为O(n3),空间复杂度为O(n2),参见代码如下:
 
解法一:
class Solution {
public:
string encode(string s) {
int n = s.size();
vector<vector<string>> dp(n, vector<string>(n, ""));
for (int step = ; step <= n; ++step) {
for (int i = ; i + step - < n; ++i) {
int j = i + step - ;
dp[i][j] = s.substr(i, step);
for (int k = i; k < j; ++k) {
string left = dp[i][k], right = dp[k + ][j];
if (left.size() + right.size() < dp[i][j].size()) {
dp[i][j] = left + right;
}
}
string t = s.substr(i, j - i + ), replace = "";
auto pos = (t + t).find(t, );
if (pos >= t.size()) replace = t;
else replace = to_string(t.size() / pos) + '[' + dp[i][i + pos - ] + ']';
if (replace.size() < dp[i][j].size()) dp[i][j] = replace;
}
}
return dp[][n - ];
}
};

根据热心网友iffalse的留言,我们可以优化上面的方法。如果t是重复的,是不是就不需要再看left.size() + right.size() < dp[i][j].size()了。例如t是abcabcabcabcabc, 最终肯定是5[abc],不需要再看3[abc]+abcabc或者abcabc+3[abc]。对于一个本身就重复的字符串,最小的长度肯定是n[REPEATED],不会是某个left+right。所以应该把k的那个循环放在t和replace那部分代码的后面。这样的确提高了一些运算效率的,参见代码如下:

解法二:

class Solution {
public:
string encode(string s) {
int n = s.size();
vector<vector<string>> dp(n, vector<string>(n, ""));
for (int step = ; step <= n; ++step) {
for (int i = ; i + step - < n; ++i) {
int j = i + step - ;
dp[i][j] = s.substr(i, step);
string t = s.substr(i, j - i + ), replace = "";
auto pos = (t + t).find(t, );
if (pos < t.size()) {
replace = to_string(t.size() / pos) + "[" + dp[i][i + pos - ] + "]";
if (replace.size() < dp[i][j].size()) dp[i][j] = replace;
continue;
}
for (int k = i; k < j; ++k) {
string left = dp[i][k], right = dp[k + ][j];
if (left.size() + right.size() < dp[i][j].size()) {
dp[i][j] = left + right;
}
}
}
}
return dp[][n - ];
}
};

类似题目:

Decode String

Number of Atoms

参考资料:

https://leetcode.com/problems/encode-string-with-shortest-length/

https://leetcode.com/problems/encode-string-with-shortest-length/discuss/95599/Accepted-Solution-in-Java

https://leetcode.com/problems/encode-string-with-shortest-length/discuss/95605/Easy-to-understand-C%2B%2B-O(n3)-solution

https://leetcode.com/problems/encode-string-with-shortest-length/discuss/95619/C%2B%2B-O(N3)-time-O(N2)-space-solution-using-memorized-dynamic-programming-with-detail-explanations

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Encode String with Shortest Length 最短长度编码字符串的更多相关文章

  1. Leetcode: Encode String with Shortest Length && G面经

    Given a non-empty string, encode the string such that its encoded length is the shortest. The encodi ...

  2. Leetcode 8. String to Integer (atoi) atoi函数实现 (字符串)

    Leetcode 8. String to Integer (atoi) atoi函数实现 (字符串) 题目描述 实现atoi函数,将一个字符串转化为数字 测试样例 Input: "42&q ...

  3. 【LeetCode每天一题】Length of Last Word(字符串中最后一个单词的长度)

    Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the l ...

  4. [LeetCode] Construct String from Binary Tree 根据二叉树创建字符串

    You need to construct a string consists of parenthesis and integers from a binary tree with the preo ...

  5. [LeetCode] Decode String 解码字符串

    Given an encoded string, return it's decoded string. The encoding rule is: k[encoded_string], where ...

  6. LeetCode : Given a string, find the length of the longest serial substring without repeating characters.

    Given a string, find the length of the longest serial substring without repeating characters. Exampl ...

  7. Leetcode 943. Find the Shortest Superstring(DP)

    题目来源:https://leetcode.com/problems/find-the-shortest-superstring/description/ 标记难度:Hard 提交次数:3/4 代码效 ...

  8. hust--------The Minimum Length (最短循环节)(kmp)

    F - The Minimum Length Time Limit:1000MS     Memory Limit:131072KB     64bit IO Format:%lld & %l ...

  9. [LeetCode] Reverse String II 翻转字符串之二

    Given a string and an integer k, you need to reverse the first k characters for every 2k characters ...

随机推荐

  1. React-Native学习系列(一)

    近段时间一直在忙,所以博客也没有更新,这两天我翻了一下写的这几篇博客,感觉写的都很片面,所以,我想重新写一个系列教程,从最基础的开始,来让大家更容易学会React-Native. 这个系列大部分只介绍 ...

  2. Devexpress Ribbon Add Logo

    一直在网上找类似的效果.在Devpexress控件里面的这个是一个Demo的.没法查看源代码.也不知道怎么写的.所以就在网上搜索了半天的. 终于找到类似的解决办法. 可以使用重绘制的办法的来解决. [ ...

  3. ViEmu 3.6.0 过期 解除30天限制的方法

    下载:链接: http://pan.baidu.com/s/1c2HUuWw 密码: sak8 删除下面2个地方 HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{B9CDA4 ...

  4. shiro实现session共享

    session共享:在多应用系统中,如果使用了负载均衡,用户的请求会被分发到不同的应用中,A应用中的session数据在B应用中是获取不到的,就会带来共享的问题. 假设:用户第一次访问,连接的A服务器 ...

  5. JVM之内存结构

    JVM是按照运行时数据的存储结构来划分内存结构的.JVM在运行Java程序时,将他们划分成不同格式的数据,分别存储在不同的区域,这些数据就是运行时数据.运行时数据区域包括堆,方法区,运行时常量池,程序 ...

  6. Scala 变长参数

    如果Scala定义变长参数 def sum(i Int*), 那么调用sum时,可以直接输入sum(1,2,3,4,5) 但是不可以sum(1 to 5) 必须要将1 to 5 强制为seq sum( ...

  7. iOS:小技巧(不断更新)

    记录下一些不常用技巧,以防忘记,复制用. 1.获取当前的View在Window的frame: UIWindow * window=[[[UIApplication sharedApplication] ...

  8. 拖拽手势和清扫手势冲突时(UIPanGestureRecognizer和UISwipeGestureRecognizer冲突时)

    故事发生在这样的情境上:给整个控制器添加了一个拖拽手势,然后又在控制上的每个Cell上加了左滑清扫手势,然后问题来了:只有拖拽手势起作用,而左滑手势没有效果了,然后怎么解决这个问题呢!先上图: 当给整 ...

  9. Android窗口机制分析与UI管理系统

    类图关系 在看Android的窗口机制之前,先看看其主要的类图关系以及层级之间的依赖与调用关系 1.window在当前的android系统的中的呈现形式是PhoneWindow (frameworks ...

  10. MAC OS X El CAPITAN 搭建SPRING MVC (1)- 目录、包名、创建web.xml

    一. 下载STS(Spring Tool Suite) 官方地址:http://spring.io/tools/sts 下载spring tool suite for mac 最新版本.这个IDE是很 ...