本文仅讨论动态规划的方法。状态转移方程容易理解,递归版本不难看懂。自底而上的版本不强求,以实际案例跟着推演一遍,有点感觉即可
备忘录递归
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数组:
0 | 1 | 2 | 1 | 2 |
0 | 0 | 1 | 0 | 1 |
0 | 0 | 0 | 1 | 2 |
0 | 0 | 0 | 0 | 1 |
0 | 0 | 0 | 0 | 0 |