【C++刷题】优选算法——动态规划第四辑

  1. 回文子串
状态表示:
	dp[i][j]: 表示以i位置开始,j位置结尾的子串是否是回文串
状态转移方程:
	i == j: dp[i][j] = true;
	i + 1 == j && s[i] == s[j]: dp[i][j] = true;
	i + 1 < j && dp[i+1][j-1] && s[i] == s[j]: dp[i][j] = true;
int countSubstrings(string s)
{
    // 1.dp数组
    vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false));

    // 2.初始化

    // 3.状态转移方程
    for(int i = s.size() - 1; i >= 0; --i)
    {
        for(int j = i; j < s.size(); ++j)
        {
            if(i == j)
            {
                dp[i][j] = true;
            }
            else if(i + 1 == j)
            {
                if(s[i] == s[j]) dp[i][j] = true;
            }
            else
            {
                if(dp[i+1][j-1] && s[i] == s[j]) dp[i][j] = true;
            }
        }
    }

    // 4.返回值
    int ret = 0;
    for(int i = s.size() - 1; i >= 0; --i)
    {
        for(int j = i; j < s.size(); ++j)
        {
            ret += dp[i][j];
        }
    }
    return ret;
}
  1. 最长回文子串
状态表示:
	dp[i][j]: 表示以i位置开始,j位置结尾的子串是否是回文串
状态转移方程:
	i == j: dp[i][j] = true;
	i + 1 == j && s[i] == s[j]: dp[i][j] = true;
	i + 1 < j && dp[i+1][j-1] && s[i] == s[j]: dp[i][j] = true;
string longestPalindrome(string s) 
{
    // 1.dp数组
    vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false));

    // 2.初始化

    // 3.状态转移方程
    for(int i = s.size() - 1; i >= 0; --i)
    {
        for(int j = i; j < s.size(); ++j)
        {
            if(i == j)
            {
                dp[i][j] = true;
            }
            else if(i + 1 == j)
            {
                if(s[i] == s[j]) dp[i][j] = true;
            }
            else
            {
                if(dp[i+1][j-1] && s[i] == s[j]) dp[i][j] = true;
            }
        }
    }

    // 4.返回值
    int start = -1, end = -1;
    for(int i = s.size() - 1; i >= 0; --i)
    {
        for(int j = i; j < s.size(); ++j)
        {
            if(dp[i][j] == true)
            {
                if(start == -1)
                {
                    start = i;
                    end = j;
                }
                else
                {
                    if(j - i > end - start)
                    {
                        start = i;
                        end = j;
                    }
                }
            }
        }
    }
    return s.substr(start, end - start + 1);
}
  1. 分割回文串 IV
状态表示:
	dp[i][j]: 表示以i位置开始,j位置结尾的子串是否是回文串
状态转移方程:
	i == j: dp[i][j] = true;
	i + 1 == j && s[i] == s[j]: dp[i][j] = true;
	i + 1 < j && dp[i+1][j-1] && s[i] == s[j]: dp[i][j] = true;
bool checkPartitioning(string s)
{
    // 1.dp数组
    vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false));

    // 2.初始化

    // 3.状态转移方程
    for(int i = s.size() - 1; i >= 0; --i)
    {
        for(int j = i; j < s.size(); ++j)
        {
            if(i == j) dp[i][j] = true;
            else if(i + 1 == j && s[i] == s[j]) dp[i][j] = true;
            else if(dp[i+1][j-1] && s[i] == s[j]) dp[i][j] = true;
        }
    }

    // 4.返回值
    for(int i = 1; i < s.size() - 1; ++i)
    {
        for(int j = i; j < s.size() - 1; ++j)
        {
            if(dp[0][i-1] && dp[i][j] && dp[j+1][s.size() - 1]) return true;
        }
    }
    return false;
}
  1. 分割回文串 II
状态表示:
	dp[i]: 表示 s[0, i]这个子串区间,最少的分割次数
状态转移方程:
	dp[i] = min(dp[j-1]+1)
int minCut(string s)
{
    // 0.优化
    vector<vector<bool>> vv(s.size(), vector<bool>(s.size(), false));
    for(int i = s.size() - 1; i >= 0; --i)
    {
        for(int j = i; j < s.size(); ++j)
        {
            if(i == j) vv[i][j] = true;
            else if(i + 1 == j && s[i] == s[j]) vv[i][j] = true;
            else if(vv[i+1][j-1] && s[i] == s[j]) vv[i][j] = true;
        }
    }

    // 1.dp数组
    vector<int> dp(s.size());

    // 2.初始化

    // 3.状态转移方程
    for(int i = 0; i < dp.size(); ++i)
    {
        if(vv[0][i]) dp[i] = 0;
        else
        {
            int m = INT_MAX;
            for(int j = i; j > 0; --j)
            {
                if(vv[j][i]) m = min(m, dp[j-1] + 1);
            }
            dp[i] = m;
        }
    }
    // 4.返回值
    return dp.back();
}
  1. 最长回文子序列
状态表示:
	dp[i][j]: 表示s字符串[i,j]区间内的所有子序列中,最长回文子序列的长度
状态转移方程:
	s[i] == s[j]:
		if(i == j) dp[i][j] = 1;
        else if(i + 1 == j) dp[i][j] = 2;
        else dp[i][j] = dp[i+1][j-1] + 2;
    s[i] != s[j]:
    	dp[i][j] = max(dp[i+1][j], dp[i][j-1]);
int longestPalindromeSubseq(string s)
{
    // 1.dp数组
    vector<vector<int>> dp(s.size(), vector<int>(s.size()));

    // 2.初始化

    // 3.状态转移方程
    for(int i = s.size() - 1; i >= 0; --i)
    {
        for(int j = i; j < s.size(); ++j)
        {
            if(s[i] == s[j])
            {
                if(i == j) dp[i][j] = 1;
                else if(i + 1 == j) dp[i][j] = 2;
                else dp[i][j] = dp[i+1][j-1] + 2;
            }
            else
            {
                dp[i][j] = max(dp[i+1][j], dp[i][j-1]);
            }
        }
    }

    // 4.返回值
    return dp[0][s.size() - 1];
}
  1. 让字符串成为回文串的最少插入次数
状态表示:
	dp[i][j]: 表示s字符串中[i,j]区间的子串,成为回文串的最小插入次数
状态转移方程:
	s[i] == s[j]:
		if(i == j || i + 1 == j) dp[i][j] = 0;
        else dp[i][j] = dp[i+1][j-1];
    s[i] != s[j]:
    dp[i][j] = min(dp[i+1][j], dp[i][j-1]) + 1;
int minInsertions(string s)
{
    // 1.dp数组
    vector<vector<int>> dp(s.size(), vector<int>(s.size()));

    // 2.初始化

    // 3.状态转移方程
    for(int i = s.size(); i >= 0; --i)
    {
        for(int j = i; j < s.size(); ++j)
        {
            if(s[i] == s[j])
            {
                if(i == j || i + 1 == j) dp[i][j] = 0;
                else dp[i][j] = dp[i+1][j-1];
            }
            else
            {
                dp[i][j] = min(dp[i+1][j], dp[i][j-1]) + 1;
            }
        }
    }

    // 4.状态转移方程
    return dp[0][s.size() - 1];
}

相关推荐

  1. C++优选算法——动态规划

    2024-04-22 00:12:01       35 阅读
  2. C++优选算法——动态规划

    2024-04-22 00:12:01       37 阅读
  3. C++优选算法——动态规划

    2024-04-22 00:12:01       27 阅读
  4. C++优选算法——递归第一

    2024-04-22 00:12:01       32 阅读
  5. C++】校招笔试编程第一

    2024-04-22 00:12:01       46 阅读
  6. C++优选算法——模拟

    2024-04-22 00:12:01       35 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-22 00:12:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-22 00:12:01       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-22 00:12:01       82 阅读
  4. Python语言-面向对象

    2024-04-22 00:12:01       91 阅读

热门阅读

  1. 【LeetCode热题100】【动态规划】最长递增子序列

    2024-04-22 00:12:01       36 阅读
  2. 2015NOIP普及组真题 2. 扫雷游戏

    2024-04-22 00:12:01       32 阅读
  3. OpenMP:变量作用域

    2024-04-22 00:12:01       37 阅读
  4. 代码随想录算法训练营day41

    2024-04-22 00:12:01       32 阅读
  5. Mysql优化

    2024-04-22 00:12:01       35 阅读
  6. spring的refresh

    2024-04-22 00:12:01       38 阅读
  7. 如何防止服务器被攻击

    2024-04-22 00:12:01       34 阅读
  8. CSS 预处理器

    2024-04-22 00:12:01       39 阅读