使字符串成为回文串插入的最少字符数

本文仅讨论动态规划的方法。状态转移方程容易理解,递归版本不难看懂。自底而上的版本不强求,以实际案例跟着推演一遍,有点感觉即可

备忘录递归 

class my_2DAry {
public:
    //typedef typename T value_type;
    T** pp;
    int m_l, m_c;
    my_2DAry(int l, int c):m_l(l), m_c(c) {
        pp = new T* [l];
        for (int i = 0; i < l; i++)pp[i] = new T[c];
    }
    ~my_2DAry() {
        for (int i = 0; i < m_l; i++)delete[] pp[i];
        delete[] pp;
    }
    void print() {
        for (int i = 0; i < m_l; i++) {
            for (int j = 0; j < m_c; j++)cout << pp[i][j] << ' ';
            cout << endl;
        }
    }
    bool setElem(int l, int c, int e) {
        if (l > m_l || c > m_c)return false;
        pp[l][c] = e;
        return true;
    }
    void init(T e) {
        for (int i = 0; i < m_l; i++)
            memset(pp[i], e, m_c*sizeof(T));
    }
};

int Palindromic(const char* s) {
    if (!s)return 0;
    int len = 0;
    const char* s2 = s;
    while (*s2++ != '\0')len++;
    if (!len)return 0;
    my_2DAry<int> dp(len, len);//自定义的一个包含二维数组的模板类
    dp.init(-1);

    class A {
    public:
        static int func(int x, int y, const char* s, int** aa) {
            if (x >= y)return 0;//终止条件
            if (aa[x][y] != -1)return aa[x][y];
            //{int i = 0; while (s[i] != '\0') { cout << s[i]; i++; }cout << "123" << endl; }
            if (s[x] != s[y]) {
                aa[x][y] = std::min(A::func(x, y - 1, s, aa), A::func(x + 1, y, s, aa)) + 1;
            }
            else {
                aa[x][y] = A::func(x + 1, y - 1, s, aa);
            }

            return aa[x][y];
        }
    };

    A::func(0, len - 1, s, dp.pp);
    return dp.pp[0][len - 1];
}

void test02() {
    const char* s = "abqwca";//abqcwcqba    //3
    cout << Palindromic(s) << endl;
}

自底而上 

int Palindromic(const char* s) {
    if (!s)return 0;
    int len = 0;
    const char* s2 = s;
    while (*s2++ != '\0')len++;
    if (!len)return 0;
    my_2DAry<int> dp(len, len);
    dp.init(0);//必须初始化为0?

    for (int i = len - 2; i >= 0; i--)
        for (int j = i + 1; j < len; j++)
            if (s[i] == s[j])dp.pp[i][j] = dp.pp[i + 1][j - 1];
            else dp.pp[i][j] = std::min(dp.pp[i + 1][j], dp.pp[i][j - 1]) + 1;
    return dp.pp[0][len - 1];
}

下面以案例12325推演

dp数组:

01212
00101
00012
00001
00000

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值