刷题记录:牛客NC23501小A的回文串

传送门:牛客

题目描述:

小A非常喜欢回文串,当然我们都知道回文串这种情况是非常特殊的。所以小A只想知道给定的一个字符
串的最大回文子串是多少,但是小A对这个结果并不是非常满意。现在小A可以对这个字符串做一些改
动,他可以把这个字符串最前面的某一段连续的字符(不改变顺序)移动到原先字符串的末尾。那么请问小
A通过这样的操作之后(也可以选择不移动)能够得到最大回文子串的长度是多少。
输入:
dcbaabc
输出:
7

说实话这道题的范围其实还没到使用马拉车算法的时候,还没到1e5,我们的区间dp还是可以一试的

主要思路:

  1. 关于这道题我们可以使用 d p [ l ] [ r ] dp[l][r] dp[l][r]来记录 区间 [ l , r ] 区间[l,r] 区间[l,r]是不是回文子串.那么显然的,我们可以枚举我们的区间的长度,然后当我们枚举的区间 [ l , r ] [l,r] [l,r]的两端点的字符相同时,我们的该区间是不是回文子串就由 [ l + 1 , r − 1 ] [l+1,r-1] [l+1,r1]来决定了.
  2. 关于边界处理也是十分简单的,假设我们的端点相等,只要是我们的回文子串的长度小于等于3时肯定都是回文串即可
  3. 关于我们的将前半部分的字符移动到我们的后面,我们可以使用环拆成链的思想,只要复制一遍我们的原字符串即可.并且枚举的时候保证我们的长度为原长度

下面是具体的代码部分:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
#define root 1,n,1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {
	ll x=0,w=1;char ch=getchar();
	for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
	return x*w;
}
#define maxn 1000000
#define ll_maxn 0x3f3f3f3f3f3f3f3f
const double eps=1e-8;
string s;
bool dp[5005*2][5005*2];
int main() {
	cin>>s;
	int lens=s.length();
	s=s+s;
	s=' '+s;
	int ans=-inf;
	for(int len=1;len<=lens;len++) {
		for(int l=1;l+len-1<=2*lens;l++){
			int r=l+len-1;
			if(s[l]==s[r]) {
				if(r-l<3) dp[l][r]=true;
				else dp[l][r]=dp[l+1][r-1];
			}
			else dp[l][r]=false;
			if(dp[l][r]) ans=max(ans,r-l+1);
		}
	}
	cout<<ans<<endl;
	return 0;
}

你可能感兴趣的:(c++算法,算法,动态规划,c++)