1040 Longest Symmetric String (25分)

问题

Given a string, you are supposed to output the length of the longest symmetric sub-string. For example, given Is PAT&TAP symmetric?, the longest symmetric sub-string is s PAT&TAP s, hence you must output 11.
Input Specification:

Each input file contains one test case which gives a non-empty string of length no more than 1000.
Output Specification:

For each test case, simply print the maximum length in a line.
Sample Input:

Is PAT&TAP symmetric?

Sample Output:

11

解决方法

题目大意

就是求一个字符串里面最长回文字符串。

思路

暴力解法

这种解法是因为测试点对时间的要求比较和蔼,所以能过。要是稍微苛刻一点,不能全部AC…

#include<iostream>
#include<string>
using namespace std;
bool issymmetric(int start, int end, string s)
{
	for (int i = start; i <= (end+start)/2+1; i++)
	{
		if (s[i] != s[end--]) return false;
	}
	return true;
}
int main()
{
	string s;
	int len=0, maxlen=1;
	getline(cin, s);
	for (int i = 0; i < s.size(); i++)
	{
		for (int j = i + 1; j < s.length(); j++)
		{
			if (issymmetric(i, j, s)) len = j - i+1;
			if (len > maxlen) maxlen = len;
		}
	}
	printf("%d", maxlen);
	return 0;
}

dp

LCS

分析:在经典的LCS中:
dp[i][j]是A1…Ai和B1…Bj对应的LCS长度。对于dp[i+1][j+1]:
♦A[i+1]​=B[j+1​] dp[i+1][j+1]=dp[i][j]+1
♦A[i+1]!=B[j+1] dp[i+1][j+1]=max(dp[i+1][j],dp[i][j+1])
而此题则可以说是求两个字符串(原来的字符串翻转后和本身)的最长相同子串问题.关系式变成如下:
当A[i+1]=B[j+1] dp[i+1][j+1]=dp[i][j]+1
当A[i+1]!=B[j+1] dp[i+1][j+1]=0
不相同的字符加上去后,就会导致字符串不相等。

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int dp[1005][1005] = { 0 }, maxn = 1;
int main()
{
	string s1, s2;
	getline(cin, s1);
	s2 = s1;
	reverse(s1.begin(), s1.end());
	for (int i = 0; i < s1.size(); i++)
	{
		for (int j = 0; j < s2.size(); j++)
		{
			if (s1[i] == s2[j])
			{
				dp[i + 1][j + 1] = dp[i][j] + 1;
				maxn = max(maxn, dp[i + 1][j + 1]);
			}
			else dp[i + 1][j + 1] = 0;
		}
	}
	printf("%d", maxn);
	return 0;
}
直接dp

分析:dp[i][j]表示s[i]到s[j]所表示的字串是否是回⽂字串。只有0和1,递推⽅程为:
1 当s[i] == s[j] : dp[i][j] = dp[i+1][j-1]
2 当s[i] != s[j] : dp[i][j] =0
3 边界:dp[i][i] = 1, dp[i][i+1] = (s[i] == s[i+1]) ? 1 : 0
⾸先初始化dp[i][i] = 1, dp[i][i+1],把⻓度为1和2的都初始化好,然后从L = 3开始⼀直到 L <= len 根据动态规划的递归⽅程来判断(参考柳神)

#include<iostream>
#include<string>
using namespace std;
int dp[1010][1010] = { 0 }, maxn = 1;
int main()
{
	string s;
	getline(cin, s);
	for (int i = 0; i < s.size(); i++)
	{
		dp[i][i] = 1;
		if (i < (s.size() - 1)&&s[i]==s[i+1])
		{
			dp[i][i + 1] = 1;
			maxn = 2;
		}
	}
	for (int L = 3; L <= s.size(); L++)
	{
		for (int i = 0; i+L-1< s.size(); i++)
		{
			int j = i + L - 1;
			if (s[i] == s[j] && dp[i + 1][j-1] == 1)
			{
				dp[i][j] = 1;
				maxn = L;
			}
		}
	}
	printf("%d\n", maxn);
	return 0;
}

中心扩展

#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
int main()
{
	int maxn = 1;
	string s1,s2;
	getline(cin, s1);
	for (int i = 0; i < s1.size(); i++)
	{
		s2 += '&';
		s2 += s1[i];
	}
	s2 += '&';
	for (int i = 1; i < s2.size(); i++)
	{
		int step = 1, l, r;
		for (l = i - 1, r = i + 1; l >= 0 && r < s2.size(); l--, r++)
		{
			if (s2[l] != s2[r]) break;
			step += 2;
		}
		maxn = max(maxn, step);
	}
	printf("%d", maxn/2);
	return 0;
}

后记

这道题是一道非常经典的题,对应LeetCode上的1005,方法众多,我只能写出这么几种了。。。。。。。。。
这道题非常值得学习!

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值