SAM 习题题解

news/2025/3/9 20:34:30/文章来源:https://www.cnblogs.com/Eliauk-FP/p/18761318

不多说了,直接看题吧。

哦对,由于本人极其厌恶 SAM,所以大部分题都是拿 SA 写的,但会提供 SAM 思路(有时候也会提供 SA 思路)。

P3804 【模板】后缀自动机(SAM)

模板题,在 Parent 树上树形 DP 即可。

P3975 [TJOI2015] 弦论

如果 \(t = 0\),那么万事大吉。但是我们有万恶的 \(t = 1\),所以还得处理一下每个等价类的大小。

这题是真恶心,先是 WA 了所有 \(t = 0\),然后搞定 \(t = 0\) 后又 WA 了所有 \(t = 1\),哎。

Code
#include <bits/stdc++.h>
#define int long long 
using namespace std;const int N = 2e6 + 10;
int n, t, k;
int la, tot;
int le[N], lk[N];
int ch[N][26];
int f[N], g[N];
bool vis[N];
vector <int> tr[N];
string s, ans;void insert(string s, int n) {lk[0] = -1;for (int i = 0; i < n; i++) {int x = s[i] - 'a', p = la, cur = ++tot; le[cur] = le[p] + 1;f[cur] = 1;while (p != -1 && !ch[p][x]) {ch[p][x] = cur;p = lk[p];}if (p == -1) lk[cur] = 0;else {int q = ch[p][x];if (le[q] == le[p] + 1) lk[cur] = q;else {int cp = ++tot;le[cp] = le[p] + 1, lk[cp] = lk[q];for (int j = 0; j < 26; j++) {ch[cp][j] = ch[q][j];}while (p != -1 && ch[p][x] == q) {ch[p][x] = cp;p = lk[p];}lk[q] = lk[cur] = cp;}}la = cur;}for (int i = 1; i <= tot; i++) {tr[lk[i]].push_back(i);}
}
void dfs1(int u) {for (int i = 0; i < tr[u].size(); i++) {int v = tr[u][i];dfs1(v);f[u] += f[v];}
}
void dfs2(int u) {if (vis[u]) return ;vis[u] = 1;for (int i = 0; i < 26; i++) {int v = ch[u][i];//cout << v << ' ';if (!v) continue;dfs2(v);g[u] += g[v];}
}
void dfs3(int u, int k) {//cout << endl << f[u] << endl;if (k <= f[u]) return ;k -= f[u];for (int i = 0; i < 26; i++) {int v = ch[u][i];if (!v) continue;if (k > g[v]) k -= g[v];else {cout << char(i + 'a');dfs3(v, k);return ;}}
}signed main() {//freopen("1.in", "r", stdin);cin >> s >> t >> k;assert(t == 1);n = s.length();insert(s, n);dfs1(0);f[0] = 0;for (int i = 1; i <= tot; i++) {if (!t) f[i] = g[i] = 1;else g[i] = f[i];}dfs2(0);if (g[0] < k) {cout << -1 << "\n";return 0;}dfs3(0, k);//cout << ans;return 0;
}

SP1811 LCS - Longest Common Substring

\(S\) 建出 SAM,在 \(S\) 中匹配 \(T\),失配则跳后缀链接,最后取 \(\max\) 即可。

先粘个 SA 代码,SAM 代码以后再补。

Code
#include <bits/stdc++.h>
using namespace std;const int N = 2e6 + 10;
int tn, sn, a[N], cf[N];
int n, m, c[N], ans;
int sa[N], rk[N], ht[N];
int b[N], tp[N];
int col[N], ct[N], cnt;
int q[N], hd = 1, tl;
char ts[N];void f_sort() {for (int i = 1; i <= m; i++) b[i] = 0;for (int i = 1; i <= n; i++) b[rk[i]]++;for (int i = 1; i <= m; i++) b[i] += b[i - 1];for (int i = n; i; i--) sa[b[rk[tp[i]]]--] = tp[i];
}
void g_sa() {for (int i = 1; i <= n; i++) rk[i] = c[i], tp[i] = i;f_sort();int p = 0;for (int w = 1; w <= n; w <<= 1) {if (p == n) break;p = 0;for (int i = n - w + 1; i <= n; i++) tp[++p] = i;for (int i = 1; i <= n; i++) {if (sa[i] > w) tp[++p] = sa[i] - w;}f_sort(), swap(rk, tp), rk[sa[1]] = p = 1;for (int i = 2; i <= n; i++) {int sl = sa[i - 1], sr = sa[i];if (tp[sl] == tp[sr] && tp[sl + w] == tp[sr + w]) {rk[sa[i]] = p;} else rk[sa[i]] = ++p;}m = p;}
}
void g_hei() {int k = 0;for (int i = 1; i <= n; i++) {if (!rk[i]) continue;if (k) k--;while (c[i + k] == c[sa[rk[i] - 1] + k]) ++k;ht[rk[i]] = k;}
}int main() {m = 1e5, tn = 2;for (int i = 1; i <= tn; i++) {scanf("%s", ts + 1);int sn = strlen(ts + 1);for (int j = 1; j <= sn; j++) {c[++n] = ts[j], col[n] = i;}c[++n] = m - i; }g_sa(), g_hei();ht[1] = 1e9;int l = 1, r = 0;while (l <= n) {#define cr col[sa[r]]#define cl col[sa[l]]while (r < n && cnt < tn) {if (col[sa[++r]]) cnt += !ct[cr], ct[cr]++;while (hd <= tl && ht[q[tl]] >= ht[r]) tl--;q[++tl] = r;}if (cnt < tn) break;ans = max(ans, ht[q[hd]]);if (col[sa[l]]) ct[cl]--, cnt -= !ct[cl];while (hd <= tl && q[hd] == l + 1) hd++;l++;#undef cr#undef cl}cout << ans;return 0;
}

P6640 [BJOI2020] 封印

考虑和上一题一样的思路,在 \(t\) 中匹配 \(s\),你会发现你可以求出 \(s\) 的每个前缀在 \(t\) 中的最长后缀,记为 \(f_i\)

然后你就会发现答案形如:

\[\max_{i = l} ^ r \min \{ f_i, i - l + 1 \} \]

直接二分答案即可。

我实在不想写万恶的 SAM 了,所以这题也用 SA 了。

Code
#include <bits/stdc++.h>
using namespace std;const int N = 1e6 + 10;
const int I = 1e9 + 10;
int n, m, q, l1, l2;
int sa[N], rk[N], b[N], tp[N];
int ht[N], f[N][20], g[N], lg[N];
char c[N], c1[N], c2[N];void f_sort() {for (int i = 1; i <= m; i++) b[i] = 0;for (int i = 1; i <= n; i++) b[rk[i]]++;for (int i = 1; i <= m; i++) b[i] += b[i - 1];for (int i = n; i; i--) sa[b[rk[tp[i]]]--] = tp[i]; 
} 
void g_sa() {for (int i = 1; i <= n; i++) rk[i] = c[i], tp[i] = i;f_sort();int p = 0;for (int w = 1; w <= n; w <<= 1) {if (p == n) continue;p = 0;for (int i = n - w + 1; i <= n; i++) tp[++p] = i;for (int i = 1; i <= n; i++) {if (sa[i] > w) tp[++p] = sa[i] - w;}f_sort(), swap(rk, tp), rk[sa[1]] = p = 1;for (int i = 2; i <= n; i++) {int sl = sa[i - 1], sr = sa[i];if (tp[sl] == tp[sr] && tp[sl + w] == tp[sr + w]) {rk[sa[i]] = p;} else rk[sa[i]] = ++p;}m = p;}
}
void g_hei() {int k = 0;for (int i = 1; i <= n; i++) {if (!rk[i]) continue;if (k) k--;while (c[i + k] == c[sa[rk[i] - 1] + k]) ++k;ht[rk[i]] = k;}
}
void g_as() {for (int i = 1; i <= n; i++) {if (sa[i] <= l1) continue;int lcp = I;for (int j = i + 1; j <= n; j++) {if (sa[j] > l1) break;g[sa[j]] = lcp = min(lcp, ht[j]);}}for (int i = n; i; i--) {if (sa[i] <= l1) continue;int lcp = I;for (int j = i - 1; j; j--) {if (sa[j] > l1) break;g[sa[j]] = max(g[sa[j]], lcp = min(lcp, ht[j + 1]));}}
}
void init() {lg[0] = -1;for (int i = 1; i <= n; i++) lg[i] = lg[i >> 1] + 1;for (int i = 1; i <= n; i++) f[i][0] = g[i];for (int j = 1; j <= lg[n]; j++) {for (int i = 1; i + (1 << j) - 1 <= n; i++) {f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);}} 
}
int qry(int l, int r) {int k = lg[r - l + 1];return max(f[l][k], f[r - (1 << k) + 1][k]); 
}
int solve(int l, int r) {if (l > r) swap(l, r);int L = 0, R = r - l + 1;while (L < R) {int M = (L + R + 2) >> 1;//cout << l << ' ' << r - M + 1 << ' ' << qry(l, r - M + 1) << endl;if (qry(l, r - M + 1) >= M) L = M;else R = M - 1;}return L;
}int main() {cin >> c1 + 1 >> c2 + 1;l1 = strlen(c1 + 1), l2 = strlen(c2 + 1);//cout << l1 << ' ' << l2 << ' ';for (int i = 1; i <= l1; i++) c[++n] = c1[i];for (int i = 1; i <= l2; i++) c[++n] = c2[i];m = 127;g_sa(), g_hei(), g_as(), init();cin >> q; 	while (q--) {int l, r;cin >> l >> r;cout << solve(l, r) << "\n";} return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/896083.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于IEKF迭代扩展卡尔曼滤波算法的数据跟踪matlab仿真,对比EKF和UKF

1.程序功能描述 基于IEKF迭代扩展卡尔曼滤波算法的数据跟踪matlab仿真,对比EKF和UKF.仿真输出误差收敛曲线和误差协方差收敛曲线。 2.测试软件版本以及运行结果展示MATLAB2022A版本运行 (完整程序运行后无水印) 3.核心程序for i=1:Lekf-1z =…

Winform控件命名规则

C#控件命名规范控件分类控件名称命名规范说明数据显示控件DataGridViewdgv 数据绑定和定位控件BindingSourcebds BindingNavigatorbdn 文本编辑控件TextBoxtxt RichTextBoxrtxt MaskedTextBoxmtxt 信息显示控件Labellbl LinkLabelllbl StatusTripst ProgressBarpb 网页显示控件…

VMware中三种网络的区别

目录桥接模式仅主机模式NAT网络模式 桥接模式桥接模式 在Linux中,桥接模式通常指的是网络桥接(Network Bridging),它是一种将多个网络接口连接在一起的技术,形成一个局域网(LAN),使它们能够像在同一个网络中一样通信。仅主机模式仅主机网络 在仅主机模式下,虚拟网络是…

UE5之使用C++显示瞄准准星

1.创建控件蓝图 首先右键 用户界面---控件蓝图,创建一个控件蓝图CrosshairWidget,默认继承自UserWidget。在CrosshairWidget中新建一个Canvas Panel,再创建一个Image,加入准星图像并设置位置居中,这样准星的UI就完成了。 再添加一个图像,将其绘制为圆形盒体,这样就得到了…

20242802 2024-2025-2 《网络攻防实践》第二周作业

20242802 2024-2025-2 《网络攻防实践》第二周作业 目录 目录20242802 2024-2025-2 《网络攻防实践》第二周作业1. 实验要求2. 实验相关知识点nmap工具使用3. 实验详细过程3.1 从www.besti.edu.cn、baidu.com、sina.com.cn中选择一个DNS域名进行查询,获取如下信息:3.2尝试获取…

UE5之瞄准视角的俯仰偏移

1.创建瞄准姿势 复制瞄准动画,删除其中多余的帧,只保留瞄准的一帧,将其创建为一个单帧动画。然后将其复制成三份,分别用于表示瞄准三个姿势的up,middle,down。 将middle姿势动画的Additive动画类型修改为网格体空间,因为我们需要在网格空间创建叠加动画。基础姿势修改为…

2K star!三分钟搭建企业级后台系统,这款开源Java框架绝了!

"LikeAdmin Java是基于Spring Boot + Mybatis Plus + Vue 3的快速开发平台,内置RBAC权限管理、工作流引擎、数据可视化、三方登录等核心模块,助力开发者快速构建企业级中后台管理系统"2K star!三分钟搭建企业级后台系统,这款开源Java框架绝了!"LikeAdmin J…

震惊!C++程序真的从main开始吗?99%的程序员都答错了

嘿,朋友们好啊!我是小康。今天咱们来聊一个看似简单,但实际上99%的C++程序员都答错的问题:C++程序真的是从main函数开始执行的吗? 如果你毫不犹豫地回答"是",那恭喜你,你和大多数人一样——掉进了C++的第一个陷阱!别担心,等你看完这篇文章,你就能成为那个与…

11套!量产15W~1000W开关电源电路全套方案资料合集!

本系列小编给大家带来了15W到1000W完整量产版开关电源全系列,全套资料分期给大家分享。每套资料都包含详细的原理图,PCB图,变压器图纸,共模电感图纸,磁环图纸!点击下方链接获取! 15W开关电源方案👆👆👆(点击下载) 25W开关电源方案👆👆👆(点击下载) 30W开…

【每日一题】20250309

我所渴望的,不过是过上一种发自本心的生活,为什么竟会如此困难?【每日一题】已知 \(\odot C\) 过点 \(P(1,2)\),与 \(y\) 轴相交于点 \(Q(0,6)\).若过点 \(Q\) 作 \(\odot C\) 的切线 \(l\),其切线 \(l\) 与 \(x\) 轴平行,则 \(l\) 的方程为_________,\(\odot C\) 的标…

FastAPI Cookie 和 Header 参数完全指南:从基础到高级实战

title: FastAPI Cookie 和 Header 参数完全指南:从基础到高级实战 🚀 date: 2025/3/9 updated: 2025/3/9 author: cmdragon excerpt: 本教程深入探讨 FastAPI 中 Cookie 和 Header 参数的读取与设置,涵盖从基础操作到高级用法。通过详细的代码示例、课后测验和常见错误解…