列表

详情


NC20224. [JSOI2016]扭动的回文串

描述

JYY有两个长度均为 N 的字符串 AB。 一个“扭动字符串 S(i,j,k)A 中的第 i 个字符到第 j 个字符组成的子串 与 B 中的第 j 个字符到第 k 个字符组成的子串拼接而成。
比如,若 A='XYZ’,B='UVW’,则扭动字符串 S (1,2,3)='XYVW’。
JYY定义一个“扭动的回文串”为如下情况中的一个:
1.A 中的一个回文串;
2.B 中的一个回文串;
3.或者某一个回文的扭动字符串 S(i,j,k)
现在JYY希望找出最长的扭动回文串。

输入描述

第一行包含一个正整数 N
第二行包含一个长度为 N 的由大写字母组成的字符串 A
第三行包含一个长度为 N 的由大写字母组成的字符串 B

输出描述

输出的第一行一个整数,表示最长的扭动回文串。

示例1

输入:

5
ABCDE
BAECB

输出:

5

说明:

最佳方案中的扭动回文串如下所示(不在回文串中的字符用.表示):
.BC..
..ECB

示例2

输入:

1
A
A

输出:

2

说明:

样例2、3、4为牛客补充数据,非省选原数据,此样例已加入到判题的测试数据中。(2022.9.6更新)

示例3

输入:

2
ZZ
AZ

输出:

3

示例4

输入:

1
E
A

输出:

1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 484ms, 内存消耗: 2688K, 提交时间: 2020-08-22 21:19:27

#include<bits/stdc++.h>
using namespace std;

const int maxn=2e5+10;
int p[maxn*2];//p数组需要开至少字符串两倍的空间
string s1,s2;
int p1[maxn];
int p2[maxn];

void Manacher(string &str,int p[])
{
	string s="$#";
	int len=str.size();
	for(int i=0;i<len;i++){
		s+=str[i];
		s+='#';
	}
	int mx=0,id=0,reslen=0,rescenter=0,start=0;
	len=s.length();
	for(int i=1;i<=len;i++){
		if(mx>i) p[i]=min(p[2*id-i],mx-i);
		else p[i]=1;
		while(s[i+p[i]]==s[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;        //最长回文的中点
			start=(i-p[i]+2)/2-1;   //最长回文的起点
		}
	}
	str=s;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
	int n;
	cin>>n>>s1>>s2;
	int ans=1;
	Manacher(s1,p1);
	Manacher(s2,p2);
    for(int i=2;i<s1.size();i++){
        int x=max(p1[i],p2[i-2]);
        //cout<<x<<endl;
        while(s1[i-x]==s2[i+x-2]) x++;
        ans=max(ans,x);
    }
    cout<<ans-1<<endl;
	return 0;
}

C++(clang++ 11.0.1) 解法, 执行用时: 407ms, 内存消耗: 2900K, 提交时间: 2022-09-04 22:09:52

#include <bits/stdc++.h>
#define ll long long
#define mod 998244353
using namespace std;
const int N=2e5+7;
string s1,s2;
int p1[N],p2[N],n;
void manacher(string &s,int p[]){
	string str="$#";
	for(int i=0;i<n;i++){
//		str=str+s[i]+'#';
		str+=s[i];
		str+='#';
	}
	int len=str.length();
	int mx=0,id=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;
		}
	}
	s=str;
}


int main(){
	cin>>n;
	cin>>s1>>s2;
	manacher(s1,p1);
	manacher(s2,p2);
	int len=s1.length(),ans=1;
	for(int i=2;i<len;i++){
		int x=max(p1[i],p2[i-2]);
		while(s1[i-x]==s2[i-2+x]) x++;
		ans=max(ans,x);
	}
	printf("%d\n",ans-1);
}

上一题