刷题记录:牛客NC23501小A的回文串
传送门:
题目描述:
小A非常喜欢回文串,当然我们都知道回文串这种情况是非常特殊的。所以小A只想知道给定的一个字符 串的最大回文子串是多少,但是小A对这个结果并不是非常满意。现在小A可以对这个字符串做一些改 动,他可以把这个字符串最前面的某一段连续的字符(不改变顺序)移动到原先字符串的末尾。那么请问小 A通过这样的操作之后(也可以选择不移动)能够得到最大回文子串的长度是多少。 输入: dcbaabc 输出: 7
说实话这道题的范围其实还没到使用马拉车算法的时候,还没到1e5,我们的区间dp还是可以一试的
主要思路:
- 关于这道题我们可以使用 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,r−1]来决定了.
- 关于边界处理也是十分简单的,假设我们的端点相等,只要是我们的回文子串的长度小于等于3时肯定都是回文串即可
- 关于我们的将前半部分的字符移动到我们的后面,我们可以使用环拆成链的思想,只要复制一遍我们的原字符串即可.并且枚举的时候保证我们的长度为原长度
下面是具体的代码部分:
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <map> #include <set> #include <queue> #include <string.h> #include <stack> #include <deque> 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; }
上一篇:
通过多线程提高代码的执行效率例子