SA 后缀数组 / SAM 后缀自动机 c++ 模板

2023-10-27

文章目录


前言

SA 后缀数组模板
SAM 后缀自动机模板

代码

1.SA

#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 1e6 + 6;
char s[maxn];
int rk[maxn], sa[maxn], height[maxn];
int sa2[maxn], oldrk[maxn], tank[maxn];
int n, m;
bool cmp(int x, int y, int w) {
  return oldrk[x] == oldrk[y] && oldrk[x + w] == oldrk[y + w];
}
void rsort() {  // sa2为基数排序而构造
  for (int i = 1; i <= m; i++) tank[i] = 0;
  for (int i = 1; i <= n; i++) tank[rk[sa2[i]]]++;
  for (int i = 2; i <= m; i++) tank[i] += tank[i - 1];
  for (int i = n; i >= 1; i--) sa[tank[rk[sa2[i]]]--] = sa2[i];
}
void getSA() {
  for (int i = 1; i <= n; i++) rk[i] = s[i], sa2[i] = i;
  rsort();  // 对SA进行基数排序
  for (int k = 1; k <= n; k <<= 1) {
    int cnt = 0;  // 对第二关键字的SA2进行排序(非计数排序)
    for (int i = n - k + 1; i <= n; i++) sa2[++cnt] = i;
    for (int i = 1; i <= n; i++)
      if (sa[i] > k) sa2[++cnt] = sa[i] - k;
    rsort();  // 对SA进行基数排序(与rk本质同,只是排序的方式不同)
    swap(rk, oldrk);
    cnt = 1;  // 对rk进行倍增比较排序
    rk[sa[1]] = 1;
    for (int i = 2; i <= n; i++) {
      if (cmp(sa[i], sa[i - 1], k))
        rk[sa[i]] = cnt;
      else
        rk[sa[i]] = ++cnt;
    }
    m = cnt;
  }
}
void getHI() {
  int k = 0;
  for (int i = 1; i <= n; i++) {
    if (rk[i] == 1) continue;
    int j = sa[rk[i] - 1];
    if (k) k--;
    while (i + k <= n && j + k <= n && s[i + k] == s[j + k]) k++;
    height[rk[i]] = k;
  }
}
int main() {
  // freopen("in.txt", "r", stdin);
  // freopen("out.txt", "w", stdout);
  scanf("%s", s + 1);
  n = strlen(s + 1);
  m = 127;
  getSA();
  getHI();
  printf("rk: ");
  for (int i = 1; i <= n; i++) printf("%d ", rk[i]);
  printf("\n");
  printf("sa: ");
  for (int i = 1; i <= n; i++) printf("%d ", sa[i]);
  printf("\n");
  return 0;
}

2.SAM

#include <cstring>
#include <iostream>
#include <map>
using namespace std;
const int maxn = 100000;
char s[maxn];
struct state {
  int len, link;
  map<char, int> next;
};
state st[maxn * 2];
int cnt, last;
void samInit() {
  st[0].len = 0;
  st[0].link = -1;
  cnt = 1;
  last = 0;
}
void samExtend(char c) {
  int cur = cnt++;
  st[cur].len = st[last].len + 1;
  int p = last;
  while (p != -1 && !st[p].next.count(c)) {
    st[p].next[c] = cur;
    p = st[p].link;
  }
  if (p == -1) {
    st[cur].link = 0;
  } else {
    int q = st[p].next[c];
    if (st[p].len + 1 == st[q].len) {
      st[cur].link = q;
    } else {
      int clone = cnt++;
      st[clone].len = st[p].len + 1;
      st[clone].next = st[q].next;
      st[clone].link = st[q].link;
      while (p != -1 && st[p].next[c] == q) {
        st[p].next[c] = clone;
        p = st[p].link;
      }
      st[q].link = st[cur].link = clone;
    }
  }
  last = cur;
}
int main() {
  //   freopen("in.txt", "r", stdin);
  //   freopen("out.txt", "w", stdout);
  scanf("%s", s);
  int len = strlen(s);
  samInit();
  for (int i = 0; i < len; i++) {
    samExtend(s[i]);
  }
  return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SA 后缀数组 / SAM 后缀自动机 c++ 模板 的相关文章

  • 用于代数简化和求解的 C# 库 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 网络上有很多代数求解器和简化器 例如 algebra com 上不错的代数求解器和简化器 然而 我正在
  • 未提供参数时如何指定 C# System.Commandline 行为?

    在我的控制台应用程序中 当未提供控制台参数时 将执行我指定列表 在本例中为参数 3 的任何处理程序 调用该处理程序时 布尔参数设置为 false 但对我来说 根本不调用它更有意义 如何防止这种情况发生并显示帮助文本 using System
  • 为什么 int8_t 和用户通过 cin 输入显示奇怪的结果[重复]

    这个问题在这里已经有答案了 一小段代码让我发疯 但希望你能阻止我跳出窗外 看这里 include
  • 如何让 Swagger 插件在自托管服务堆栈中工作

    我已经用 github 上提供的示例重新提出了这个问题 并为任何想要自己运行代码的人提供了一个下拉框下载链接 Swagger 无法在自托管 ServiceStack 服务上工作 https stackoverflow com questio
  • 复制 std::function 的成本有多高?

    While std function是可移动的 但在某些情况下不可能或不方便 复制它会受到重大处罚吗 它是否可能取决于捕获变量的大小 如果它是使用 lambda 表达式创建的 它依赖于实现吗 std function通常被实现为值语义 小缓
  • 使用 LINQ2SQL 在 ASP.NET MVC 中的各种模型存储库之间共享数据上下文

    我的应用程序中有 2 个存储库 每个存储库都有自己的数据上下文对象 最终结果是我尝试将从一个存储库检索到的对象附加到从另一个存储库检索到的对象 这会导致异常 Use 构造函数注入将 DataContext 注入每个存储库 public cl
  • 获取两个工作日之间的天数差异

    这听起来很简单 但我不明白其中的意义 那么获取两次之间的天数的最简单方法是什么DayOfWeeks当第一个是起点时 如果下一个工作日较早 则应考虑在下周 The DayOfWeek 枚举 http 20 20 5B1 5D 3a 20htt
  • 回发后刷新时提示确认表单重新提交。我做错了什么?

    我有一个以空白 默认状态启动的仪表板 我让用户能够将保存的状态加载到仪表板中 当他们单击 应用 按钮时 我运行以下代码 function CloseAndSave var radUpload find radUpload1ID var in
  • qdbusxml2cpp 未知类型

    在使用 qdbusxml2cpp 程序将以下 xml 转换为 Qt 类时 我收到此错误 qdbusxml2cpp c ObjectManager a ObjectManager ObjectManager cpp xml object ma
  • 为什么调用非 const 成员函数而不是 const 成员函数?

    为了我的目的 我尝试包装一些类似于 Qt 共享数据指针的东西 经过测试 我发现当应该调用 const 函数时 会选择它的非 const 版本 我正在使用 C 0x 选项进行编译 这是一个最小的代码 struct Data int x con
  • 如何在 Xaml 文本中添加电子邮件链接?

    我在 Windows Phone 8 应用程序中有一些大文本 我希望其中有电子邮件链接 例如 mailto 功能 这是代码的一部分
  • C#:帮助理解 UML 类图中的 <>

    我目前正在做一个项目 我们必须从 UML 图编写代码 我了解 UML 类图的剖析 但我无法理解什么 lt
  • CMake 无法确定目标的链接器语言

    首先 我查看了this https stackoverflow com questions 11801186 cmake unable to determine linker language with c发帖并找不到解决我的问题的方法 我
  • “接口”类似于 boost::bind 的语义

    我希望能够将 Java 的接口语义与 C 结合起来 起初 我用过boost signal为给定事件回调显式注册的成员函数 这非常有效 但后来我发现一些函数回调池是相关的 因此将它们抽象出来并立即注册所有实例的相关回调是有意义的 但我了解到的
  • Cmake 链接共享库:包含库中的头文件时“没有这样的文件或目录”

    我正在学习使用 CMake 构建库 构建库的代码结构如下 include Test hpp ITest hpp interface src Test cpp ITest cpp 在 CMakeLists txt 中 我用来构建库的句子是 f
  • 方法优化 - C#

    我开发了一种方法 允许我通过参数传入表 字符串 列数组 字符串 和值数组 对象 然后使用这些参数创建参数化查询 虽然它工作得很好 但代码的长度以及多个 for 循环散发出一种代码味道 特别是我觉得我用来在列和值之间插入逗号的方法可以用不同的
  • WebSocket安全连接自签名证书

    目标是一个与用户电脑上安装的 C 应用程序交换信息的 Web 应用程序 客户端应用程序是 websocket 服务器 浏览器是 websocket 客户端 最后 用户浏览器中的 websocket 客户端通过 Angular 持久创建 并且
  • 我的班级应该订阅自己的公共活动吗?

    我正在使用 C 3 0 遵循标准事件模式我有 public event EventHandler
  • 使用 .NET Process.Start 运行时挂起进程 - 出了什么问题?

    我在 svn exe 周围编写了一个快速而肮脏的包装器来检索一些内容并对其执行某些操作 但对于某些输入 它偶尔会重复挂起并且无法完成 例如 一个调用是 svn list svn list http myserver 84 svn Docum
  • 如何从 ODBC 连接获取可用表的列表?

    在 Excel 中 我可以转到 数据 gt 导入外部数据 gt 导入数据 然后选择要使用的数据源 然后在提供登录信息后 它会给我一个表格列表 我想知道如何使用 C 以编程方式获取该列表 您正在查询什么类型的数据源 SQL 服务器 使用权 看

随机推荐

  • 没有exec的参与,hasPendingConnections、nextPendingConnection等失效。

    没有exec的参与 hasPendingConnections nextPendingConnection等失效
  • (一) python+Django实现登录页面

    最近因为工作需要 开始捣鼓web框架 接下来就带大家做一个小项目 方便企业内部数据统计 调查问卷 一 操作页 二 数据填写页 三 查询页 首先我们可以找一个自己喜欢的登录页模板 不怕麻烦的话也可以自己写 我套用的是Bootstrap其中的一
  • IIC接口隔离电路ISO

    IIC为例 为什么需要隔离 隔离电路电源和数据线之间的隔离 隔离电性干扰 增强抗干扰能力 保护隔离总线iic确保系统的稳定型和可靠性 避免电源串扰以及避免数字信号对模拟信号的干扰 就需要总线进行信号隔离 就IIC而言 让master和sla
  • html5做微信公众号文章代码,微信公众号文章怎么使用代码排版?

    有了微信公众号后 就要对微信公众号进行运营 微信运营的方式就是推广文章 好的微信文章是最好的吸粉手段 那微信公众号文章怎么使用代码排版 我们一起来看看下文的例子吧 欢迎大家来阅读 需求 简单介绍下西窗烛 App 的信息结构 这是一款古诗词赏
  • 使用WSL2,开启Linux之旅

    使用WSL2 开启Linux之旅 1 确认虚拟环境的开启 2 更新WSL 3 安装ubuntu镜像 4 修改镜像路径 5 更换国内镜像源 6 配置ssh 7 配置远程桌面访问 在开始之前 提供官方链接如何更新及使用WSL 如果觉得官方操作难
  • k8s--基础--22.15--storageclass--类型--本地

    k8s 基础 22 15 storageclass 类型 本地 1 案例 kind StorageClass apiVersion storage k8s io v1 metadata name local storage provisio
  • 目标检测快速入门(含YOLO V1原理详解)

    原创 悬鱼铭 目标检测 Object Detection 任务是计算机视觉中非常重要且热门的研究方向之一 是计算机视觉算法工程师的必考的知识点 本文通过以下几点阐述 目标检测的简介 目标检测的发展 YOLO V1 原理详解 全文总共3千字左
  • DTS Audio Codec 码率

    转自 https www zhihu com question 20816979
  • 两种python实现自动发邮件的方法

    法一 from email mime text import MIMEText from email header import Header from email mime multipart import MIMEMultipart i
  • 集合框架 — ConcurrentHashMap

    集合框架 ConcurrentHashMap 一 ConcurrentHashMap JDK1 7 1 实现结构 2 保证并发安全 分段锁技术 3 put 和 get 方法 二 ConcurrentHashMap JDK1 8 1 实现结构
  • 如何实现网站文件动静分离

    背景 传统动静不分离的产品架构 随着访问量在增长 性能会成为瓶颈 以一个常见的Web站点为例 www acar com是一个刚建立汽车资讯车友交流网站 主站用Php搭建 有10GB的图片素材 部分JS文件 目前购买一台ECS放置所有程序代码
  • 使用Docker安装FastDFS

    1 获取镜像 可以利用已有的FastDFS Docker镜像来运行FastDFS 获取镜像可以通过下载 docker image pull delron fastdfs 也可是直接使用自己下载的镜像备份文件 docker load i 文件
  • HJ103 Redraiment 的走法-最长递增序列

    HJ103 Redraiment 的走法 描述 Redraiment 是走梅花桩的高手 Redraiment 可以选择任意一个起点 从前到后 但只能从低处往高处的桩子走 他希望走的步数最多 你能替 Redraiment 研究他最多走的步数吗
  • Python基础手册

    目录 第1章 Python环境准备与数据类型 分支结构 1 1 自动化测试介绍与第1个python程序 1 1 1 自动化测试介绍 1 1 2 Python环境准备 1 1 3 什么是解释器 编译型和解释型 1 1 4 第一个Python程
  • 对JSON.parse()中存在转义字符的解决以及js中替换函数replace()的认识

    在工作中 遇到对页面数据进行转存json格式数据后存储在数据库中 然而在显示数据时遇到无法显示json中的数据 产生的bug 问题抛出 1 首先认识下 在JSON parse 将后台传过来的字符串数据转存对象 遇到字符串中带有转义字符 然而
  • 使用Burpsuite进行暴力破解

    Burpsuite是一款Web安全领域的跨平台工具 基于Java开发 它集成了很多用于发现常见web漏洞的模块 如Proxy Spider Scanner Intruder Repeater等 所有模块共享一个能处理并显示HTTP消息的扩展
  • Odoo源码安装

    安装数据库 Odoo 使用 PostgreSQL 作为数据库管理系统 使用您的包管理器下载并安装 PostgreSQL sudo apt install postgresql postgresql contrib 创建用户给odoo连接访问
  • Android开发从入门到精通(3)

    第三章 下载和安装Android SDK 下载和安装Android SDK 第三章 1 关键技能和概念 下载Android SDK 使用Eclipse的可升级特性 为Eclipse下载 安装并配置Android Plugin 检查PATH声
  • 关于Dev c++的简单设置

    一 添加初始源代码 可以在工具 编辑器选项 代码 缺省源中添加初始源代码 这样每次打开软件都会帮你写好C语言必须的几行代码 二 调整代码对齐格式 在格式化选项中可以调整代码格式 我选择了allman风格 默认为Java 在编辑代码时 按住c
  • SA 后缀数组 / SAM 后缀自动机 c++ 模板

    文章目录 前言 代码 1 SA 2 SAM 前言 SA 后缀数组模板 SAM 后缀自动机模板 代码 1 SA include