首页 > 编程语言 >常用字符串算法

常用字符串算法

时间:2024-02-20 21:12:23浏览次数:39  
标签:10 常用 .. 后缀 sum leq 算法 字符串

KMP

我们考虑朴素的字符串匹配过程。

void match(const string& s, const string& p) { 
    // find p in s
    for (int i=0; i<s.size(); ++i)
        for (int j=0; j<p.size()&&i+j<s.size(); ++j) {
            if (s[i+j]!=p[j]) break;
            if (j==p.size()-1) {
                cout<<"matched at "<<i<<'\n';
            }
        }

}

对一个字符串 \(s\),定义 \(\pi[s]\) 为 \(s\) 中最长公共前后缀的长度。其中的意思是,其长度必须严格小于 \(|s|\)。

形式化地,定义

\[\pi[s]=\max_{s[1..i]=s[|s|-i+1..|s|],i\lt |s|}\{i\} \]

AC 自动机

CF1202E You Are Given Some Strings...

Disclaimer:题解的变量与题目有不同。

定义 \(f(s;p)\) 为 \(p\) 在 \(s\) 中的出现次数。求出

\[\sum_{i=1}^n\sum_{j=1}^n f(s;p_i+p_j) \]

其中 \(+\) 代表字符串拼接操作。\(\sum |p_i|,|s|,n\leq 2\times 10^5\)。

我们考虑求出 \(f_i\) 表示有多少个字符串的后缀是 \(s[1..i]\),\(g_i\) 表示有多少个字符串的前缀是 \(s[i..|s|]\)。于是这部分的贡献为

\[\sum_{i=1}^{|s|-1} f_i\cdot g_{i+1} \]

而 \(f,g\) 很易用 AC 自动机求出,具体地,在插入 Trie 树的时候给路径终止的节点的 \(ed\gets ed+1\),考虑 \(s[i]\) 对应的节点是 \(u\),则 \(f_i=ed_u\);对于 \(g\) 可以倒过来做。时间复杂度 \(\Theta(n|\Sigma|)\)。

P3715 [BJOI2017] 魔法咒语

给定 \(n\) 个基本字符串 \(s_i\) 和 \(m\) 个禁止字符串 \(p_i\);给定正整数 \(l\)。求用基本字符串拼接得到满足以下条件的字符串 \(T\) 的方案数,对 \((10^9+7)\) 取模:

  • \(|T|=l\);
  • \(T\) 中不存在任意一个 \(m_i\) 作为子串。

对于 \(1\sim 6\) 号测试点,\(n,m\leq 50\),\(l\leq 10^2\);

对于 \(7\sim 10\) 号测试点,\(|s_i|\leq 2\),\(l\leq 10^8\)。

保证 \(\sum |s_i|,\sum |m_i|\leq 10^2\)。

对于前一部分,套路地考虑 dp。设 \(f[l,i]\) 为长度为 \(l\) 时,在节点 \(i\) 处的方案数量。于是设 \(u\overset{s_i}{\to}v_{u,s_i}\),我们有

\[f[i+|s_i|,v_{u,s_i}]\gets f[i,u]+f[i+|s_i|,v_{u,s_i}] \]

其中要求 \(u\to v_{u,s_i}\) 不能经过 \(p_i\) 的终止节点。于是这一部分时间复杂度为 \(\Theta(l\sum|s_i|\sum|p_i|)\),极限数据下不大于 \(10^6\),可以通过。

对于后一部分,基于 \(|s_i|\leq 2\),考虑矩阵快速幂优化。

后缀数组

后缀自动机

P2463 [SDOI2008] Sandy 的卡片

给定 \(n\) 个数列 \(A_i,\cdots,A_n\)。求这 \(n\) 个数列的最长公共子串长度。

“相同”的定义:\(a_i\) 与 \(b_i\) 相同当且仅当 \(a_1-b_1=a_2-b_2=\cdots=a_n-b_n\)。

值域为 \([0,2\times 10^3]\),\(n\leq 10^3\)。

标签:10,常用,..,后缀,sum,leq,算法,字符串
From: https://www.cnblogs.com/Starrykiller/p/18024058/string-theory

相关文章

  • 限流算法
    固定时间窗比如1秒钟限制访问100次,则用1秒作为时间窗,用个计数器,下个时间窗到了就把计数器置0;实现方式可以用一个线程定时1秒钟刷一次,但在某些系统中,可能会有很多个qps拦截器,这样会导致线程数很多,所以也可以改成记录上次时间窗的时间点,每次计数器+1之前算一下时间窗是否超过1秒了......
  • Java_8 常用容器
    title:(在线学习平台)link:(https://www.acwing.com/)cover:(https://cdn.acwing.com/media/activity/surface/log.png)8.1List接口:java.util.List<>。实现:java.util.ArrayList<>:变长数组java.util.LinkedList<>:双链表函数:add():在末尾添加一个元素clear():清空siz......
  • 基于yolov2深度学习网络的血细胞检测算法matlab仿真
    1.算法运行效果图预览 2.算法运行软件版本MATLAB2022a 3.算法理论概述         血细胞检测是医学图像处理领域的重要任务之一,对于疾病的诊断和治疗具有重要意义。近年来,深度学习在医学图像处理领域取得了显著成果,尤其是目标检测算法在血细胞检测方面表现出......
  • 【C++】判断回文字符串。回文指的是顺读和逆读都一样的字符串。例如,“tot”和“otto”
    //判断字符串是否是回文字符串(考虑大小写,空格和标点符号)boolpalindrome1(string&str){stringret;for(auto&c:str){if(isalpha(c)){if(isupper(c)){ret.push_back(tolower(c));}else{ret.push_back(c);}......
  • 基于huffman编解码的图像压缩算法matlab仿真
    1.算法运行效果图预览 2.算法运行软件版本matlab2022a 3.算法理论概述       Huffman编码是一种用于无损数据压缩的熵编码算法。由DavidA.Huffman在1952年提出。该算法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫做Huffm......
  • 代码随想录算法训练营第二十三天|669. 修剪二叉搜索树 ● 108.将有序数组转换为二叉
    669.修剪二叉搜索树 题目链接:669.修剪二叉搜索树-力扣(LeetCode)思路:本题原来想沿用上一次最后一道题的思路,用删除二叉搜索树特定值节点的方法来解决,但是会报错,找不出问题所在(在评论区也是一堆套用450代码报错的)。只能参考官网答案了。官网的方法没有用delete,但是思想是一直......
  • 2024年2月18日——KMP算法(未完成
    点击查看代码#include<bits/stdc++.h>usingnamespacestd;constintmaxn=1e6+10;intkmp[maxn];intla,lb,j;chara[maxn],b[maxn];intmain(){ cin>>a+1>>b+1; la=strlen(a+1),lb=strlen(b+1); for(inti=2;i<=lb;i++){ while(j&&b[j+1......
  • 智能视频监控平台智能边缘分析一体机视频监控平台AI算法智能检测人员违规打电话
    在数字化时代的浪潮中,智能视频监控平台如同一双无所不见的眼睛,默默守护着我们的安全。而在这些平台中,智能边缘分析一体机以其独特的AI算法和智能检测功能,成为了维护规范和秩序的得力助手。今天,让我们一同探索这项技术如何在不断演进中,为我们的社会带来更加安全和高效的保障。......
  • delphi按键值对重组字符串
    问题背景:有一组基金代码串,原逻辑按基金代码单个调整为按父子基金代码组作为条件获取查询结果解决原理:采用TStringList类哈希表操作方式重组字符串List:=TStringList.Create;List.Add('aaa=111');List.Add('bbb=222');List.Add('ccc=333');List.Add('ddd=444');ShowMessag......
  • 十六进制字符串,转化为十六进制数据并write 写出去
    如果你想使用write函数以十六进制方式发送数据,你需要将十六进制数据转换为字节,并将字节作为参数传递给write函数。下面是一个示例程序,演示如何将十六进制字符串转换为字节,并使用write函数发送数据:#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<st......