mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
12 字
1 分钟
字符串-Manacher
2026-09-18

板子#

string s;
// 预处理成Manacher字符串
string manacherss(const string& s){
int n=s.size()*2+1;
string ss;
ss.resize(n);
for(int i=0,j=0;i<n;i++){
ss[i]=(i&1)==0?'#':s[j++];
}
return ss;
}
int manacher(const string& s){
string ss=manacherss(s);
int ans=0,ssn=ss.size();
vector<int> dp(ssn,0);
for(int i=0,c=0,r=0,len;i<ssn;i++){
len=r>i?min(dp[2*c-i],r-i):1;
while(i+len<ssn&&i-len>=0&&ss[i+len]==ss[i-len]){
len++;
}
if(i+len>r){
r=i+len;
c=i;
}
ans=max(ans,len);
dp[i]=len;
}
return ans-1;
}

例题#

K. Two-Tone Palindromes#

Manacher+滑动窗口

int n;
string s,ss;
string manacherss(const string& s){
int n=s.size()*2+1;
string ss;
ss.resize(n);
for(int i=0,j=0;i<n;i++){
ss[i]=(i&1)==0?'#':s[j++];
}
return ss;
}
ll manacher(const string& s){
string ss=manacherss(s);
int ssn=ss.size();
vector<int> dp(ssn,0),b(ssn,0);
for(int i=0,c=0,r=0,len;i<ssn;i++){
len=r>i?min(dp[2*c-i]+1,r-i):1;
while(i+len<ssn&&i-len>=0&&ss[i+len]==ss[i-len]){
len++;
}
if(i+len>r){
r=i+len;
c=i;
}
dp[i]=len-1;
}
ll ans=0;
// 统计一段中只有两种字符的最大长度的左端点
vector<int> dic(26,0);
int cnt=0;
for(int l=0,r=0;r<ssn;r++){
if(ss[r]!='#'){
if(dic[ss[r]-'a']==0){
cnt++;
}
dic[ss[r]-'a']++;
}
while(cnt>2){
if(ss[l]!='#'){
if(dic[ss[l]-'a']==1){
cnt--;
}
dic[ss[l]-'a']--;
}
l++;
}
b[r]=l;
}
int q=0;
for(int i=0;i<ssn;i++){
if(i>0){
q=max(0,q-1);
}
while(i-q-1>=0&&i+q+1<ssn&&b[i+q+1]<=i-q-1){
q++;
}
int r=min(dp[i],q);
ans+=(r+1)/2;
}
return ans;
}
void solve(){
cin>>n>>s;
cout<<manacher(s)<<"\n";
}
分享

如果这篇文章对你有帮助,欢迎分享给更多人!

字符串-Manacher
https://blog.hydrodyio.xyz/posts/字符串-manacher/
作者
Hydroiody
发布于
2026-09-18
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录