一、题目
L2-008 最长对称子串
分数 25
全屏浏览
切换布局
作者 陈越
单位 浙江大学
对给定的字符串,本题要求你输出最长对称子串的长度。例如,给定Is PAT&TAP symmetric?,最长对称子串为s PAT&TAP s,于是你应该输出11。
输入格式:
输入在一行中给出长度不超过1000的非空字符串。
输出格式:
在一行中输出最长对称子串的长度。
二、题解
法一:暴力两边扩展(O(n^2))
- 求回文字子串,首先我们可以将原字符串用原字符串不存在的字符隔开,这样就变成了奇数串!
- 我们可以枚举每一个字符,以该字符为中心向两边扩展,扩展的最大步数,即为最长回文子串的长度!
- 时间复杂度O(n^2),数据范围只有1e3,可以过
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define endl "\n"
#define int long long
#define fi first
#define se second
const int N = 1e5+10, INF = 0x3f3f3f3f;
void solve() {
int ans=0,cnt=0;
string a;
getline(cin,a);
char s[N];
int len=a.size();
s[++cnt]='#';
for(int i=0;i<len;i++) //将每个字符隔开,变为奇数串
s[++cnt]=a[i],s[++cnt]='#';
// printf("%s\n",s+1);
for(int i=1;i<=cnt;i++){
int l=i-1,r=i+1,sum=0;
while(l>0&&r<=cnt&&s[l]==s[r]) //向两边扩展
l--,r++,sum++;
ans=max(ans,sum); //取较大值
}
cout<<ans;
}
signed main() {
// IOS;
int T=1;
// cin>>T;
while(T--) {
solve();
}
return 0;
}
/*
Is PAT&TAP symmetric?
11
*/
法二:manacher(O(n))
- 第二种方法就是马拉车算法了,可以线性的求出最长回文子串的长度!
- 该算法的核心就是充分利用之前已求出的回文串,来计算当前的回文串。
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define endl "\n"
#define int long long
#define fi first
#define se second
const int N = 1e5+10, INF = 0x3f3f3f3f;
int p[N]; //回文半径
void solve() {
int ans=0,cnt=0;
string a;
getline(cin,a);
char s[N];
int len=a.size();
s[++cnt]='#';
for(int i=0;i<len;i++) //将每个字符隔开,变为奇数串
s[++cnt]=a[i],s[++cnt]='#';
int M=0,R=0; //对称点M,区间右端点R
for(int i=1;i<=cnt;i++){
if(i<=R) p[i]=min(p[2*M-i],R-i+1); //在区间内
while(i-p[i]>0&&i+p[i]<=cnt&&s[i-p[i]]==s[i+p[i]])
++p[i]; //暴力扩展
if(i+p[i]-1>R) //更新区间
M=i,R=i+p[i]-1;
}
for(int i=1;i<=cnt;i++)
ans=max(ans,p[i]);
cout<<ans-1;
}
signed main() {
// IOS;
int T=1;
// cin>>T;
while(T--) {
solve();
}
return 0;
}
/*
Is PAT&TAP symmetric?
11
*/