动态规划的方法判断字符串是否为回文串
先找状态
假如状态 F(i) : 前i个字符是否为回文串
那么F(i-1)表示前i-1个字符串为回文串, F[i]要和F[0]比较,那么此时就无法进行比较
我们需要往小区间转换,所以一维的解决不了问题
状态F(i,j):区间(i,j)是否为回文串
F(i,j)转移方程:
- s[i] == s[j] && (i+1,j-1) 是否为回文串 。 也就是 s[i] == s[j] && F(i+1,j-1)
- 两个字符的情况: F(i,j) i+1==j 双字符区间:也就是 s[i] ==s[j]
初始化: 区间(i,i): 单字符 : F(i,i) = true
返回: F(0,s.size() - 1)
那么我们要知道更新的时候 怎么更新 ?
更新第i行的值 要用到 i+1 行的值。所以要从下往上更新,从最后一行的值
代码如下
vector<vector<bool>> palMat(string s)
{
int row = s.size();
vector<vector<bool>> Mat(row, vector<bool>(row, false));
for (int i = row - 1; i >= 0; i--)
{
for (int j = i; j < row; ++j)
{
//F(i,j) = true;
if (i == j)
Mat[i][j] = true;
else if (j == i + 1)
Mat[i][j] = s[i] == s[j];
else
Mat[i][j] = s[i] == s[j] && Mat[i + 1][j - 1];//s[i]是否等于s[j] && 小区间是否为回文串
}
}
return Mat;
}
int main()
{
string s("aba");
vector<vector<bool>> Mat = palMat(s); //使用的时候先把矩阵的拿到
cout << Mat[0][0] << endl;
cout << Mat[0][2] << endl;
cout << Mat[2][0] << endl;
system("pause");
}
结果:
解释:
Mat[i][j]的含义就是从字符i到字符j是否为回文串,是的话就是true,不是的话就是false。而且值得注意的地方时,我们更新的时候是从下往上更新的,而且只更新了半个三角形。所以i的值必须小于等于j,即(i <= j), 因为没有更新的三角形我们默认给的都是false。
字符串s(aba)从下标[0]到[2]是回文串,则为真(1);从下标[0]到下标[0]是一个字符’a’也为真(1); 从[2]到[0]则为假,输出0.
这与我们平时判断是否为回文串有点不同。但是我们可以稍加改动。 但它是一种比较新颖的方法,更能在众多判断是都为回文串的方法中脱颖而出。也综合了我们的动态规划。这种在方法在某些oj题中,可以作为一个判断是否回文串的一个二维数组,用起来更加的方便,简单。
变成我们经常使用的形式,传参的时候不仅仅传字符串s,而且传要判断的起始下标和终止下标。
稍加改动之后
#include <iostream>
#include <vector>
#include <string>
using namespace std;
bool palMat(string s , int start, int end)
{
vector<vector<bool>> Mat(end+1, vector<bool>(end+1, false));
for (int i = end ; i >= start; --i)
{
for (int j = i; j < end + 1; ++j)
{
//F(i,i) = true;
if (j == i)
Mat[i][j] = true;
else if (j == i + 1)
Mat[i][j] = s[i] == s[j];
else
Mat[i][j] = s[i] == s[j] && Mat[i + 1][j - 1];
}
}
return Mat[start][end];
}
int main()
{
string s("aaabba");
cout << palMat(s, 2, 5) << endl; // abba true(1)
cout << palMat(s, 4, 5) << endl; // ba false(0)
cout << palMat(s, 3, 4) << endl; // bb true(1)
cout << palMat(s, 0, 2) << endl; // aaa true(1)
cout << palMat(s, 0, 3) << endl; // aaab false(0)
system("pause");
}
结果:
我们以palMat(s,2,5) 为例,解释一下这种方法。