D2. Prefix-Suffix Palindrome (Hard version)-----------------------------------思维(马拉车)

150 篇文章 0 订阅
2 篇文章 0 订阅

在这里插入图片描述
在这里插入图片描述

题意:
给定一个字符串s。
求一个最长回文子串t=a+b (a是s的前缀,b是s的后缀)
解析:

首先遍历前后缀相同的一部分,如果没有剩余一段,那么整个串就是最长回文子串

如果有剩余的一段为[l,r],就对[l,r]这段跑马拉车 求出这部分最大前缀回文或最大后缀回文即可 设为x
最长回文子串就为: [0,l]+x+[r+1,n]

#include<bits/stdc++.h>
#define Min(a,b) a>b?b:a
using namespace std;
const int N=2e6+10000;
char s[N],str[N];
int p[N];
int len,n,f;
int ans;
int t;
void init(int l,int r)
{
	int k=0;
	str[k++]='@';
	for(int i=l;i<=r;i++)
	{
		str[k++]='#';
		str[k++]=s[i];
	}
	str[k++]='#';
	len=k;
	str[k]='\0';
	
}
void mlc()
{
	int mx=0,id=0;
	p[0]=0;
	for(int i=1;i<len;i++)
	{
		if(i<mx) p[i]=min(mx-i,p[2*id-i]);
		else p[i]=1;
		while(str[i-p[i]]==str[i+p[i]]) p[i]++;
		if(i+p[i]>mx)
		{
			mx=i+p[i];
			id=i;
		}
		if(p[i]==i)
		{
			if(ans<p[i])
			{
				ans=p[i]-1;
				f=1;
			}
		}
		if(p[i]+i==len)
		{
			if(ans<p[i])
			{
				ans=p[i]-1;
				f=2;
			}
		}
	}
}
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		f=0;
		ans=0;
		scanf("%s",s);
		 n=strlen(s);
		int l=0,r=n-1;
		while(s[l]==s[r]&&l<r)//去除相同的前缀和后缀
		{
			l++;
			r--;
		}
		if(l>=r)
		{
			cout<<s<<endl;
			continue;
		}
		init(l,r); 
		mlc();
		for(int i=0;i<l;i++) printf("%c",s[i]);
		if(f==1) //输出[l,r]这一段的最长回文前缀部分
		{
			for(int i=l,j=0;j<ans;i++,j++)  printf("%c",s[i]);
		}
		else//输出[l,r]这一段的最长回文后缀部分
		{
			for(int i=r-ans+1;i<=r;i++)  printf("%c",s[i]);
		}
		//输出剩下的一段
		for(int i=r+1;i<n;i++)  printf("%c",s[i]);
		puts("");
	}
 } 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值