给定一个字符串S ,任务是找到最短压缩字符串的长度。字符串可以通过以下方式压缩:
- 如果 S = “ABCDABCD” ,则字符串可以压缩为(ABCD) 2 ,因此压缩字符串的长度将为4 。
- 如果 S = “AABBCCDD”,则字符串压缩形式将为A 2 B 2 C 2 D 2因此,压缩字符串的长度将为4 。
例子:
Input: S = “aaba”
Output: 3
Explanation : It can be rewritten as a2ba therefore the answer will be 3.
Input: S = “aaabaaabccdaaabaaabccd”
Output: 4
Explanation: The string can be rewritten as (((a)3b)2(c)2d)2. Therefore, the answer will be 4.
方法:该问题可以使用动态规划解决,因为它具有最优子结构和重叠子问题。请按照以下步骤解决问题:
- 初始化一个dp[][]向量,其中dp[i][j]存储压缩子串s[i], s[i+1], …, s[j]的长度。
- 使用变量l在范围[1, N] 中迭代并执行以下步骤:
- 使用变量i在范围[0, Nl] 中迭代并执行以下步骤:
- 将变量j初始化为i+l-1。
- 如果i等于j,则 将dp[i][j]更新为1并继续。
- 使用变量k在范围[i, j-1] 中迭代并将dp[i][j]更新为 dp[i][j]和dp[i][k] + dp[k][j] 的最小值。
- 初始化一个变量,比如temp为s.substr(i, l)。
- 然后,找到最长的前缀也是子串temp的后缀。
- 如果子串的形式为dp[i][k]^n(l%(l – pref[l-1]) = 0) ,则将dp[i][j]的值更新为min(dp [i][j], dp[i][i + (l-pref[l-1] – 1)])。
- 使用变量i在范围[0, Nl] 中迭代并执行以下步骤:
- 最后,打印dp[0][N-1] 的值作为答案。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Prefix function to calculate
// longest prefix that is also
// the suffix of the substring S
vector prefix_function(string s)
{
int n = (int)s.length();
vector pi(n);
for (int i = 1; i < n; i++) {
int j = pi[i - 1];
while (j > 0 && s[i] != s[j])
j = pi[j - 1];
if (s[i] == s[j])
j++;
pi[i] = j;
}
return pi;
}
// Function to find the length of the
// shortest compressed string
void minLength(string s, int n)
{
// Declare a 2D dp vector
vector > dp(n + 1, vector(n + 1, 10000));
// Traversing substring on the basis of length
for (int l = 1; l <= n; l++) {
// For loop for each substring of length l
for (int i = 0; i < n - l + 1; i++) {
// Second substring coordinate
int j = i + l - 1;
// If the length of the string is 1
// then dp[i][j] = 1
if (i == j) {
dp[i][j] = 1;
continue;
}
// Finding smallest dp[i][j] value
// by breaking it in two substrings
for (int k = i; k < j; k++) {
dp[i][j] = min(dp[i][j],
dp[i][k] + dp[k + 1][j]);
}
// Substring starting with i of length L
string temp = s.substr(i, l);
// Prefix function of the substring temp
auto pref = prefix_function(temp);
// Checking if the substring is
// of the form of dp[i][k]^n
if (l % (l - pref[l - 1]) == 0) {
// If yes, check if dp[i][k] is
// less than dp[i][j]
dp[i][j] = min(dp[i][j],
dp[i][i + (l - pref[l - 1] - 1)]);
}
}
}
// Finally, print the required answer
cout << dp[0][n - 1] << endl;
}
// Driver Code
int main()
{
// Given Input
int n = 4;
string s = "aaba";
// Function Call
minLength(s, n);
}
输出:
3
时间复杂度: O(N^3)
辅助空间: O(N^2)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。