【C++】动态规划法判断是否为回文串

动态规划的方法判断字符串是否为回文串

先找状态
假如状态 F(i) : 前i个字符是否为回文串
那么F(i-1)表示前i-1个字符串为回文串, F[i]要和F[0]比较,那么此时就无法进行比较
我们需要往小区间转换,所以一维的解决不了问题

状态F(i,j):区间(i,j)是否为回文串
F(i,j)转移方程:

  1. s[i] == s[j] && (i+1,j-1) 是否为回文串 。 也就是 s[i] == s[j] && F(i+1,j-1)
  2. 两个字符的情况: 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 就是
解释:
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) 为例,解释一下这种方法。
在这里插入图片描述

发布了55 篇原创文章 · 获赞 12 · 访问量 5261

猜你喜欢

转载自blog.csdn.net/weixin_43939593/article/details/103328876