最长回文子串问题求解

问题描述:

给出一个字符串S,求S的最长回文子串的长度。

例:字符串“ASDFGHGFDSB”的最长回文子串为“SDFGHGFDS”,长度为9。

显然暴力解法的复杂度较大,采用动态规划可以更好的解决这类问题。

令dp[i][j]表示S[i]至S[j]所表示的子串是否回文,是则为1,不是则为0.这样可以根据S[i]和S[j]是否相等分为两种情况:

  1. 如果S[i]==S[j],那么只要S[i+1]至S[j-1]是回文子串,那么S[i]至S[j]也是回文子串;如果S[i+1]至S[j-1]不是回文子串,那么S[i]至S[j]也不是回文子串;
  2. 如果S[i]!=S[j],那么S[i]至S[j]一定不是回文子串

 边界:dp[i][i]=1, dp[i][i+1]=(S[i]==S[i+1])?1:0

如果按照i和j从小到大的顺序来枚举子串的端点,然后更新dp[i][j],这样会无法保证dp[i+1][j-1]得到计算。

因为边界的子串长度为1和2,所以可以考虑按照子串的长度和初始位置进行枚举,即第一遍将子串长度为3的dp值全部求出来,第二遍计算长度为4的子串可以通过计算出的长度为3的子串的dp值进行计算。这样问题就可以得到解决,代码如下:

#include<cstdio>
#include<cstring>
const int maxn = 10010;
char S[maxn];
int dp[maxn][maxn];
int main()
{
	gets(S);
	int len = strlen(S);
	int ans = 1; //初始化最长回文子串长度为1 
	memset(dp, 0, sizeof(dp));
	for (int i = 0; i < len; i++)
	{
		dp[i][i] = 1;
		if (i < len - 1)
		{
			if (S[i] == S[i + 1])
			{
				dp[i][i + 1] = 1;
				ans = 2;
			}
		}
	}
	//状态转移方程
	for (int L = 3; L <= len; L++)
	{
		for (int i = 0; i + L - 1 < len; i++)
		{
			int j = i + L - 1;
			if (S[i] == S[j] && dp[i + 1][j - 1] == 1)
			{
				dp[i][j] = 1;
				ans = L;
			}
		}
	}
	printf("%d\n", ans);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值