小白月赛13 B小A的回文串 (马拉车算法求最长回文子串)
链接:https://ac.nowcoder.com/acm/contest/549/B
来源:牛客网
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
小A非常喜欢回文串,当然我们都知道回文串这种情况是非常特殊的。所以小A只想知道给定的一个字符串的最大回文子串是多少,但是小A对这个结果并不是非常满意。现在小A可以对这个字符串做一些改动,他可以把这个字符串最前面的某一段连续的字符(不改变顺序)移动到原先字符串的末尾。那么请问小A通过这样的操作之后(也可以选择不移动)能够得到最大回文子串的长度是多少。
输入描述:
一行一个字符串表示给定的字符串S一行一个字符串表示给定的字符串S
输出描述:
一行输出一个整数,表示通过这样的操作后可以得到最大回文子串的长度。
备注:
N表示字符串的长度,1≤N≤5000N表示字符串的长度,1≤N≤5000
解题思路:马拉车算法学习博客:https://www.cnblogs.com/grandyang/p/4475985.html
枚举每一种情况,跑一遍马拉车算法即可。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<string> #include<set> #include<cmath> #include<list> #include<deque> #include<cstdlib> #include<bitset> #include<stack> #include<map> #include<cstdio> #include<queue> using namespace std; typedef long long ll; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define pushup() tree[rt]=tree[rt<<1]+tree[rt<<1|1] const int INF=0x3f3f3f3f; const double PI=acos(-1.0); const double eps=1e-6; const ll mod=1e9+7; const int maxn=1000005; ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} ll lcm(ll a,ll b){return a/gcd(a,b)*b;} const int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; const int MAXN=2e6+10; int n,m,ans,p[MAXN]; string st; int Manacher(string s,int st){ string t="$#"; for(int i=st,j=0;j<n;i++,j++){ t+=s[i]; t+='#'; } //memset(p,0,sizeof(p)); int mx=0,id=0,reslen=0,rescenter=0; for(int i=1;i<t.length();i++){ p[i]=mx>i?min(p[2*id-i],mx-i):1; while(t[i-p[i]]==t[i+p[i]])p[i]++; if(mx<i+p[i]){ mx=i+p[i]; id=i; } if(reslen<p[i]){ reslen=p[i]; rescenter=i; } } return reslen-1; //return s.substr((reslen-rescenter)/2,reslen-1); } int main(){ cin>>st; n=st.length(); st=st+st; for(int i=0;i<n;i++){ ans=max(ans,Manacher(st,i)); } cout<<ans<<endl; return 0; }