新闻中心

C++怎么实现一个后缀数组_C++处理字符串问题的强大数据结构SA

2025-12-13
浏览次数:
返回列表
后缀数组是将字符串所有后缀按字典序排序后记录起始位置的数组,用于高效解决模式匹配、LCP、重复子串等问题;例如"banana"的SA为[5,3,1,0,4,2],可通过直接排序实现,或用倍增法优化至O(n log²n),结合LCP数组可拓展多种应用。

c++怎么实现一个后缀数组_c++处理字符串问题的强大数据结构sa

后缀数组(Suffix Array,简称 SA)是处理字符串问题的强大工具,相比后缀树更简洁、节省空间。它通过将字符串的所有后缀按字典序排序,记录其起始位置的索引,从而支持高效地完成模式匹配、最长公共前缀(LCP)、重复子串查找等任务。

什么是后缀数组

给定一个字符串 s,它的所有后缀是指从每个位置到末尾的子串。例如,字符串 "banana" 的后缀有:

  • banana
  • anana
  • nana
  • ana
  • na
  • a

将这些后缀按字典序排序后,得到新的顺序,后缀数组 SA 就是保存这些排序后的原起始下标。比如排序后第一个后缀是 "a",起始于下标 5,所以 SA[0] = 5。

如何用C++实现基础后缀数组

最直接的方法是生成所有后缀,排序并记录原始位置。虽然时间复杂度为 O(n² log n),但对于中等长度字符串足够实用。

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

std::vector<int> buildSuffixArray(const std::string& s) {
    int n = s.size();
    std::vector<int> sa(n);
    
    // 初始化:sa[i] = i
    for (int i = 0; i < n; ++i)
        sa[i] = i;

    // 按后缀字符串排序
    std::sort(sa.begin(), sa.end(), [&s](int i, int j) {
        return s.substr(i) < s.substr(j);
    });

    return sa;
}

// 示例使用
int main() {
    std::string s = "banana";
    auto sa = buildSuffixArray(s);

    std::cout << "Suffix Array of \"" << s << "\": ";
    for (int idx : sa)
        std::cout << idx << " ";
    std::cout << "\n";

    return 0;
}

输出结果为:
Suffix Array of "banana": 5 3 1 0 4 2

对应后缀排序为:
"a", "ana", "anana", "banana", "na", "nana"

优化思路:倍增法 + 哈希(O(n log²n))

对于更长字符串,可以使用倍增法(Doubling Method),每次比较前 2^k 个字符,配合 rank 数组进行排序,将复杂度降到 O(n log²n) 或 O(n log n)。

核心思想:

Playground AI Playground AI

AI图片生成和修图

Playground AI 99 查看详情 Playground AI
  • 维护每个位置开始的长度为 k 的子串的排名
  • 每次将 k 翻倍,利用上一轮的 rank 快速比较两个子串
  • 用 pair 进行排序

这样避免了 substr 的高开销,适合处理较长字符串。

常见应用举例

有了后缀数组,结合 LCP(最长公共前缀)数组,可以解决很多问题:

  • 查找子串出现次数:二分查找在 SA 中定位范围
  • 最长重复子串:遍历相邻后缀的 LCP 最大值
  • 最长回文子串:构造反串拼接后找 LCP
  • 多字符串公共子串:标记来源后找跨组的最长 LCP

SA 是竞赛和实际工程中处理字符串匹配、压缩、生物信息等领域的重要工具。

基本上就这些。从简单实现入手,理解原理后再过渡到高效算法,能更好地掌握这一数据结构的本质。

以上就是C++怎么实现一个后缀数组_C++处理字符串问题的强大数据结构SA的详细内容,更多请关注其它相关文章!


# 第一个  # 绮丽营销品牌推广  # 益阳网站建设优化建站  # 宽城满族自治县网站优化  # 网站设计与建设价格  # 肇庆网站推广优势  # 南城家具网站优化价格  # 烟台定制网站推广电话号  # seo从业者重要性  # 微信营销推广哪家强些呀  # 营销推广专委会  # 相关文章  # 遍历  # 是指  # c++  # 这一  # 迭代  # 命令行  # 解决方法  # 多字  # 数据结构  # stream  # ios  # ai  # 工具  # 大数据  # go  # 后缀数组 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: 修复二维数组索引越界异常:一维循环到二维坐标的正确映射  J*aScript中正确使用querySelectorAll与复杂CSS选择器  c++如何使用Catch2编写单元测试_c++简洁易用的BDD风格测试框架  高德地图公交到站提醒失败如何解决 高德提醒权限设置  mysql备份恢复性能优化_mysql备份恢复性能优化方法  Tabulator表格日期时间排序问题及自定义解决方案  利用5118提升短视频内容效果_5118短视频关键词优化方法  Gmail邮箱申请注册直达_Gmail邮箱免费注册PC版官网入口2025  文本文档写html代码怎么运行_文本文档html代码运行步骤【教程】  微信网页版登录教程_微信网页版登录入口在哪  c++中的std::forward_list和std::list有什么不同_c++ forward_list与list区别分析  蛙漫正版漫画平台入口_蛙漫免费阅读全站漫画资源  深入理解J*a合成构造器:何时以及为何阻止其生成  厨房不锈钢水槽发黑生锈怎么处理_水槽用可乐+锡纸2分钟抛亮如新  电脑IP地址怎么查 查看本机IP地址的几种方法  汽车之家官方网站官网入口_汽车之家网页版直接进入  怎么在浏览器上运行HTML文件_浏览器运行HTML文件技巧【技巧】  从J*aScript对象中精确提取指定属性的教程  Lar*el 8 多关键词数据库搜索优化实践  qq游戏网页版直接玩_qq游戏免下载快速入口  Golang如何使用buffered channel提高性能_Golang buffered channel优化技巧  微信群消息显示延迟如何解决 微信群消息刷新优化方法  夸克AO3官网入口_AO3镜像网站2025推荐  菜鸟取件码是什么怎么查 最全查询渠道汇总  红果短剧网页版官网入口 官方最新网址发布  在Blazor WebAssembly应用中动态注入客户端特定指标代码的策略  单12V-2&#215;6实现为RTX 5090供电750W!甚至都没敢跑分  Win10怎么设置静态IP地址 Win10手动配置IP地址步骤【指南】  印象笔记怎样用批量导出备知识库_印象笔记用批量导出备知识库【备份方法】  响应式容器内容自动缩放与宽高比维持教程  如何在低配置电脑上搭建轻量级J*a环境_占用更小的环境选择技巧  如何设置Windows Defender的定时扫描_计划任务实现自动杀毒【安全】  海量存储:机器视觉智能化的核心基石  地铁跑酷免费秒玩入口链接 地铁跑酷小游戏免费秒玩网站  在React函数组件中利用原生HTML5进行邮箱地址验证  高德地图沿途添加点失败如何解决 高德多点规划方法  C++如何实现单例模式_C++设计模式之线程安全的单例写法  腾讯QQ邮箱官方网站_QQ邮箱网页版在线登录  mysql密码锁定怎么解锁_mysql密码锁定解锁后修改密码步骤  夸克浏览器网页版最新地址 夸克浏览器官方入口合集  绝地鸭卫平a核爆刀流玩法攻略  印象笔记如何设提醒任务防漏执行_印象笔记设提醒任务防漏执行【任务提醒】  J*a里如何使用N*igableMap进行导航操作_可导航Map操作技巧解析  JUnit5/Mockito:优雅测试内部依赖与异常处理的实践  J*a里如何实现线程安全的懒加载单例_懒加载单例实现方法解析  QQ邮箱在线使用入口 QQ邮箱个人账号网页版登录  C++如何使用AddressSanitizer(ASan)_C++调试工具中检测内存访问错误的利器  J*aScript中针对特定容器内图片动画的实现教程  如何将HTML表格多行数据保存到Google Sheets  照顾宝贝2小游戏免费秒玩入口 

搜索