回文字符分割

题目

最美字符串
题目描述
字符串有很多格式,我们定义最美字符串为:能够对称的
比如“CBABC“, 因为字符串本身和它的反转字符串是相同的,也即字符串以中间字符为轴心呈对称展开。
现在需要您帮忙提供方案能够将任一字符串经过最少切割次数使得每个子字串都是最美字符串。

输入说明
程序从当前路径下的data.txt文件中读取测试数据。
文件内容只有一行待测字符串(只包含数字和字母,且区分大小写, 字符串长度不超过1KB)。

输出说明
向标准输出打印最少切割次数

示例1
输入:
ACDCDCDAD
最少需要切2次, 使得每个子串都变成最美字符串, 比如: A|CDCDC|DAD, 所以输出2

输出:
2

示例2
输入:
ABA
不需要切割, 字符串本身就是对称的, 所以输出0。

输出:
0

思路

  1. 这是一道动态规划问题,别用贪心~比如abacccaha,用贪心每次去分割最大的回文字符串显然是错误的。
  2. 我们设置 dp[j] 表示从0到 j 的最小的分割数,每次递增 j ,用 i 遍历 j 到 0,寻找是否有回文字符串 S i j S_{ij} Sij ,如果有,其可能的最小值为 dp[i-1] + 1。我们遍历所有可能,每次与 dp[j] 比较,则 dp[j] = min{dp[j], dp[i-1]+1},当然需要判断一下边界 i=0 的情况。
  3. 中间我们用二维数组 p[i][j] 记录 i 到 j 的子串是否为回文字符串。
  4. 时间复杂度O(n^2)

代码

#include <iostream>
#include <vector>
#include <fstream>
#include <string>

using namespace std;

int getMin(string s) {
    int len = s.length();
    int *dp = new int[len];
    vector<vector<int>> p(len, vector<int>(len));

    for (int j = 0; j<len; j++) {
        dp[j] = 999;
        for (int i = j; i >= 0; i--) {
            if (s[i] == s[j] && (j - i<2 || p[i + 1][j - 1])) {
                p[i][j] = true;
                int t = (i == 0) ? 0 : (dp[i - 1] + 1);
                if (t < dp[j]) dp[j] = t;
            }
        }
    }
    return dp[len - 1];
}

int main() {
    string s;
    fstream file("data.txt");
    file >> s;

    cout << getMin(s) << endl;
    system("pause");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值