【董晓算法】竞赛常用知识之字符串2

2024-05-13 18:04

本文主要是介绍【董晓算法】竞赛常用知识之字符串2,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言:

本系列是学习了董晓老师所讲的知识点做的笔记

董晓算法的个人空间-董晓算法个人主页-哔哩哔哩视频 (bilibili.com)

 动态规划系列(还没学完)

【董晓算法】动态规划之线性DP问题-CSDN博客

【董晓算法】动态规划之背包DP问题(2024.5.11)-CSDN博客

【董晓算法】动态规划之背包DP与树形DP-CSDN博客

字符串系列

【董晓算法】竞赛常用知识之字符串1-CSDN博客

字典树

作用:

快速插入和查询字符串

插入

儿子数组 ch[p][j] 存储从节点 p沿着j这条边走到的子节点。
边为26个小写字母(a-z)对应的映射值0-25.
每个节点最多可以有26个分叉。例如,ch[0][2]=1,ch[1][0]=2.ch[2][19]=3。

计数数组 cnt[p]存储以节点 p结尾的单词的插入次数

节点编号 idx 用来给节点编号

 1.空 Trie 仅有一个根节点,编号为0。
枚举字符串的每个字符2,从根开始插,

如果有儿子,则p指针走到儿子.
如果没儿子,则 先创建儿子,p指针再走到儿子

3、在单词结束点记录插入次数。

char s[N];
int ch[N][26], cnt[N], idx;
void insert(char* s)
{int p = 0;for (int i = 0; s[i]; i++) {int j = s[i] - 'a';if (!ch[p][j]) ch[p][j] = ++idx;p = ch[p][j];}cnt[p]++;
}
int query(char* s) {int p = 0;for (int i = 0; s[i]; i++) {int j = s[i] - 'a';if (!ch[p][j]) return 0;p = ch[p][j];}return cnt[p];
}

查询和插入最主要的就是if (!ch[p][j]) 后不一样,和查询会返回值

最大异或对

任选两个进行异或运算,得到的结果最大是多少

思路:尽可能走相反位,结果最优(从根到叶的每一条路径都表示一个整数)

const int N = 100010;
int n, a[N];
int ch[N * 31][2], idx;//题目是2的23次void insert(int x) {int p = 0;for (int i = 30; i >= 0; i--) {int j = x >> i & 1; //取出第i位if (!ch[p][j])ch[p][j] = ++idx;p = ch[p][j];}
}
int query(int x) {int p = 0, res = 0;for (int i = 30; i >= 0; i--) {int j = x >> i & 1; //取出第i位if (ch[p][!j]) {res += 1 << i; //累加位权p = ch[p][!j];}else p = ch[p][j];}return res;
}
int main() {cin >> n;for (int i = 1; i <= n; i++)cin >> a[i], insert(a[i]);int ans = 0;for (int i = 1; i <= n; i++)ans = max(ans, query(a[i]));cout << ans;return 0;
}


int query(int x) {
    int p = 0, res = 0;
    for (int i = 30; i >= 0; i--) {
        int j = x >> i & 1; //取出第i位
        if (ch[p][!j]) {
            res += 1 << i; //累加位权
            p = ch[p][!j];
        }
        else p = ch[p][j];
    }
    return res;
}

AC自动机 

AC 自动机(简单版) - 洛谷 (luogu.com.cn)

AC自动机是多模式匹配算法。给定 n个模式串和一个主串,查找有多少个模式串在主串中出现过 

步骤

1.构造 Trie 树
先用n个模式串构造一颗Trie 。
Trie 中的一个节点表示一个从根到当前节点的字符串。
根节点表示空串,节点(5表示“s”,节点6表示“sh",节点7表示“she”。
如果节点是个模式串,则打个标记。例如,cnt[7]=1。
2.构造 AC自动机在 Trie 上构建两类边:回跳边和转移边

3.扫描主串匹配

回跳边指向父节点的回跳边所指节点的儿子,从一个节点指向其最长后缀匹配节点

转移边指向当前节点的回跳边所指节点的儿子,从一个节点指向其直接子节点的链接 

 

构树代码就是上面字典树的代码 

构造 AC自动机

void build() {//建AC自动机queue<int> q;for (int i = 0; i < 26; i++)if (ch[0][i])q.push(ch[0][i]);while (q.size()) {int u = q.front(); q.pop();for (int i = 0; i < 26; i++) {int v = ch[u][i];if (v)ne[v] = ch[ne[u]][i], q.push(v);else ch[u][i] = ch[ne[u]][i];}}
}

 查找单词出现次数

 扫描主串,依次取出字符 s[k].
1.i指针走主串对应的节点,沿着树边或转移边走保证不回退。
2.j指针沿着回跳边搜索模式串,每次从当前节点走到根节点,把当前节点中的所有后缀模式串一网打尽,保证不漏解。
3.扫描完主串,返回答案。

int query(char *s){int ans=0;for(int k=0,i=0;s[k];k++){i=ch[i][s[k]-'a'];for(int j=i;j&&~cnt[j];j=ne[j])//~cnt[i]检查cnt是不是-1ans+=cnt[j], cnt[j]=-1;}return ans;
}

KMP和AC自动机对比

这篇关于【董晓算法】竞赛常用知识之字符串2的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/986428

相关文章

springboot项目中常用的工具类和api详解

《springboot项目中常用的工具类和api详解》在SpringBoot项目中,开发者通常会依赖一些工具类和API来简化开发、提高效率,以下是一些常用的工具类及其典型应用场景,涵盖Spring原生... 目录1. Spring Framework 自带工具类(1) StringUtils(2) Coll

openCV中KNN算法的实现

《openCV中KNN算法的实现》KNN算法是一种简单且常用的分类算法,本文主要介绍了openCV中KNN算法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录KNN算法流程使用OpenCV实现KNNOpenCV 是一个开源的跨平台计算机视觉库,它提供了各

MySQL更新某个字段拼接固定字符串的实现

《MySQL更新某个字段拼接固定字符串的实现》在MySQL中,我们经常需要对数据库中的某个字段进行更新操作,本文就来介绍一下MySQL更新某个字段拼接固定字符串的实现,感兴趣的可以了解一下... 目录1. 查看字段当前值2. 更新字段拼接固定字符串3. 验证更新结果mysql更新某个字段拼接固定字符串 -

Java String字符串的常用使用方法

《JavaString字符串的常用使用方法》String是JDK提供的一个类,是引用类型,并不是基本的数据类型,String用于字符串操作,在之前学习c语言的时候,对于一些字符串,会初始化字符数组表... 目录一、什么是String二、如何定义一个String1. 用双引号定义2. 通过构造函数定义三、St

golang获取当前时间、时间戳和时间字符串及它们之间的相互转换方法

《golang获取当前时间、时间戳和时间字符串及它们之间的相互转换方法》:本文主要介绍golang获取当前时间、时间戳和时间字符串及它们之间的相互转换,本文通过实例代码给大家介绍的非常详细,感兴趣... 目录1、获取当前时间2、获取当前时间戳3、获取当前时间的字符串格式4、它们之间的相互转化上篇文章给大家介

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

C#数据结构之字符串(string)详解

《C#数据结构之字符串(string)详解》:本文主要介绍C#数据结构之字符串(string),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录转义字符序列字符串的创建字符串的声明null字符串与空字符串重复单字符字符串的构造字符串的属性和常用方法属性常用方法总结摘

Java实现时间与字符串互相转换详解

《Java实现时间与字符串互相转换详解》这篇文章主要为大家详细介绍了Java中实现时间与字符串互相转换的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、日期格式化为字符串(一)使用预定义格式(二)自定义格式二、字符串解析为日期(一)解析ISO格式字符串(二)解析自定义

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时