当前位置: 首页 > news >正文

20251117 - Manacher

前言

怎么又有 ABB 啊,连考三次,罚时吃饱了!


Manacher,俗称马拉车,是一个可以线性的求出一个串的最长回文子串

如何求解最长回文子串呢? 马拉车


方法零

首先枚举字符串的左端点和右端点,在判断区间是否是回文串。

时间复杂度\(O(n^3)\)

空间复杂度\(O(n)\)

bool check(int l,int r){for(int i = l,j = r;i < j;i++,j--){if(s[i] != s[j]) return 0;}return 1;
}
for(int d = 1;d <= n;d++){ // 这是认真的吗?for(int i = 1;i + d - 1 <= n;i++){int j = i + d - 1;if(check(i,j)){ans = max(ans,j - i + 1);}}
}

方法一

枚举中间位置,再看看往两边扩充最大能到多少。

for(int i = 1;i <= n;i++){int l,r;l = r = i;while(l >= 1 && r <= n && s[l] == s[r]) l--,r++;ans = max(ans,r - l + 1);
}

方法二

通过打表严禁证明,可以发现,方法一是具有单调性的(长度),所以,就可以二分来搞。

还要用哈希来搞!

方法四:Manacher

方法三慢在扩充的过程,Manacher 就像 KMP 一样,根据已知的条件来得到最终答案。

如果回文的中心点不在上一个回文区间,那么就没有回文串与之匹配。

否则和对称的另一端和边界求一个 \(\min\)。(抄过来)

再暴力扩充即可!

void init(){s = tmp + 1;for(auto v : s){t += '$';t += v;}t = '_' + t + '$';n_ = t.size() - 1;d.resize(n_ + 2);
}
for(int mid = 1,l = 1,r = -1;mid <= n_;mid++){int len;if(mid > r){len = 1;}else{len = min(d[l+r-mid],r-mid+1);}while(mid - len >= 1 && mid + len <= n_ && t[mid-len] == t[mid+len]){len++;}d[mid] = len;if(mid + len - 1 > r){r = mid + len - 1;l = mid - len + 1;}}

例题: 拉拉队排练

首先看看 \(K\) 的范围:\(10^{12}\),如果跟 \(K\) 有关的,一定要是 \(\le log_k\)

回文子串,马拉车!

在马拉车时记录,在快速幂一下就好了!

#include <bits/stdc++.h>using namespace std;
#define ll long long
const int N = 2e6 + 7;
const int P = 19930726;
const int inf = (1 << 30);
template<class T> void read(T &x){x = 0;int f = 1;char ch = getchar();while(!(ch >= '0' && ch <= '9')){if(ch == '-') f = -f;ch = getchar();}while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}x *= f;
}
int n,n_,cnt[N];
ll k,ans = 1;
char tmp[N];
string s,t;
vector<int>d;
void init(){s = tmp + 1;for(auto v : s){t += '$';t += v;}t = '_' + t + '$';n_ = t.size() - 1;d.resize(n_ + 2);
}
int mcp(int x){return (int)ceil(x / 2.0) * 2 - 1;
}
ll ksm(ll a,ll b,ll mod){a %= mod;ll res = 1;while(b){if(b & 1){res *= a;res %= mod;}a *= a;a %= mod;b >>= 1;}return res;
}
int main(){read(n),read(k);scanf("%s",tmp+1);init();for(int mid = 1,l = 1,r = -1;mid <= n_;mid++){// 暴力扩充时会记录答案了!if(mid & 1) continue;int len;if(mid > r){len = 1;}else{len = min(d[l+r-mid],r-mid+1);}while(mid - len >= 1 && mid + len <= n_ && t[mid-len] == t[mid+len]){// cnt[mcp(len)]++;len++;}d[mid] = len;if(mid + len - 1 > r){r = mid + len - 1;l = mid - len + 1;}if(mcp(len) % 2) cnt[mcp(len)]++;}ll sum = 0;for(int i = n;i >= 1;i--){if(!(i & 1)) continue;sum += cnt[i];if(sum <= k){ans = (ans * ksm(i,sum,P)) % P;k -= sum;}else{ans = (ans * ksm(i,k,P)) % P;k -= sum;break;}}// for(int i = 1;i <= n;i++)// printf("%d %d\n",i,cnt[i]);if(k > 0) ans = -1;printf("%lld\n",ans);return 0;
}

后记

马拉车非常实用,一定要搞懂他!

http://www.zskr.cn/news/53369.html

相关文章:

  • Prufer序列和Cayley定理
  • 软件工程学习日志2025.11.18
  • 11.14 事务的四大特性 并发事务问题
  • SQL逻辑查询语句执行顺序
  • uniapp的rich-text在渲染长数字与长字母时不换行
  • 头部厂商易路AI HR实战解析:从人海战术到智能闭环的合规跃迁
  • 实用指南:【XR硬件系列】影目GO3智能眼镜发布:AI翻译+轻薄设计,重塑人机交互体验
  • 完整教程:PRCV 2025:文本何以成为 AGI 的必经之路?
  • Ubuntu Server 22.04.5 linux系统安装教程
  • 2025年最新苗木批发基地综合实力排行榜单,国槐/樱花/红叶李/苗木/金叶复叶槭/红叶石楠/丝棉木/油松/白蜡/金叶女贞/紫薇种植推荐
  • VideoLLaMA 3新一代前沿多模态基础模型赋能图像与视频深度理解| LLM | 计算机视觉
  • kotlin中HorizontalDivider() ModalBottomSheet background()
  • 11月18号
  • 2025 最新黄锈石实力厂家推荐排行榜:无辐射环保石材权威测评,光面 / 荔枝面 / 路沿石优质供应商精选黄锈石菠萝面/黄锈石滚石/黄锈石蘑菇石公司推荐
  • 毕设项目基于SpringBoot的趣味知识卡片APP\251022(白嫖源码+演示录像)可做计算机毕设JAVA、PHP、爬虫、APP、小程序、C#、C++、python、数据可视化、文案 - 实践
  • 2025 最新槽钢厂家推荐!权威测评认证的槽钢源头厂家,聚焦定制实力与万吨备货量的优选榜单轨道/导轨/集装箱用/门架/C 型槽钢公司推荐
  • 每日 Emacs Tip:Emacs Lisp 语法详解 —— 反引用(Backquote)
  • 详细介绍:【物联网架构】
  • CF1898F Vova Escapes the Matrix
  • 第四章 栈与队列--栈
  • 每日 Emacs Tip:Abbrev Mode(缩写模式)
  • mns 1118
  • 完整教程:临床研究标志物发现与机制探索:纯数据挖掘与“实验+服务”一站式方案,如何选择?
  • 2025年山东一次性打包碗商用公司权威推荐榜单:一次性餐盒/合肥一次性打包碗订制/南京一次性外卖打包碗源头公司精选
  • 2025.11.17 周作业 44 速通
  • [JOIGST 2024]-卡牌游戏 解题报告
  • 无菌药厂变频升级方案:ModbusTCP转Canopen高效适配方案
  • 31、用户授权 GRANT
  • 理解模型输出配置
  • MapStruct对象属性拷贝