📜  最小化压缩字符串的长度

📅  最后修改于: 2021-09-22 09:51:13             🧑  作者: Mango

给定一个字符串S ,任务是找到最短压缩字符串的长度。字符串可以通过以下方式压缩:

  • 如果 S = “ABCDABCD” ,则字符串可以压缩为(ABCD) 2 ,因此压缩字符串的长度将为4
  • 如果 S = “AABBCCDD”,则字符串压缩形式将为A 2 B 2 C 2 D 2因此,压缩字符串的长度将为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] 的最小值
      • 初始化一个变量,比如temps.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)])。
  • 最后,打印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 现场工作专业课程学生竞争性编程现场课程