字符串知识点

一.manacher算法

能求出以任一点为中点的回文半径(回文串长度),O(n)

二.字符串Hash

hash[i]=(hash[i-1]*seed+str[i])%MOD
将字符串通过hash函数映射成一个数字,并由此判断是否重复等,近似字符串匹配

三.KMP

字符串匹配,并求出匹配位置,O(n+m)

四.扩展KMP

求S的所有后缀与T的最长公共前缀,O(n+m)

五.字典树(Trie)

一个节点和其所有孩子都有相同的前缀,即该节点对应的字符串,或者说从根节点出发到该节点的路径,组成的子串
各种操作均为O(n)

常见用法:
1.字符串匹配
2.前缀查询
3.求连续异或和

六.01字典树

用字典树保存一个数的二进制形式(只由01构成),若想要异或值大,一定要越靠前的数异或后为1,即尽可能使权值较大的数异或后为1
常见用法:
求各种与异或相关的操作

求区间最大异或值

七.AC自动机:

结合KMP与trie,相当于在trie上构建了一个next数组,保存每个位置的失配后调整位置
用于多字符串匹配,如在匹配cat时失配,但存在另一个单词cart,则失配指针指向前缀ca,避免重复计算

AC自动机上的动态规划
Trie图上每个点都是一个状态,在AC自动机的状态相互装化,可以实现动态规划

1.求模式串在原串中出现的次数:(所有模式串不同)
构建Trie树时,在每个串结尾节点进行标记,在AC自动机上匹配时,每遇到一次结尾节点即表示成功匹配,ans++

2.求模式串在原串中出现次数,若模式串B是模式串A的子串,则只记录A:
构建Trie树时,在每个串结尾节点进行标记,在AC自动机上匹配时,对经过的子串模式串消除标记,其余与之前相同

3.求原串中不包含任何模式串的串的种类数:
对所有模式串构建AC自动机,模式串的终止的都是非法的,不可经过
dp[i][j]表示长度为i,状态为j的字符串的种类数,枚举所有字符进行状态匹配,答案即为sum(dp[m][i])
若m较小,n较大,可以考虑用矩阵乘法加速dp

4.求一个长度最短的串使得它包含所有模式串:
对所有模式串建立AC自动机,若n很小,可用状态压缩dp
二进制状态j&2^k表示从根节点到该结点的路径上有第k个模式串 dp[i][j]表示状态i,二进制状态j的最短长度,初始化dp[i][j]=0
在Trie上求(0,0)到(i,2n-1)点的最短路,答案即是dp[i][2-1]

回文自动机(回文树)
以最长回文为前缀构建的字典树,用回文串代替字典树中的前缀

常用方法:
1.求串S前缀0~i内本质不同回文串的个数(两个串长度不同或者长度相同且至少有一个字符不同便是本质不同)
2.求串S内每一个本质不同回文串出现的次数
3.求串S内回文串的个数(其实就是1和2结合起来)
4.求以下标i结尾的回文串的个数

后缀数组:
计算一个字符串所有后缀经过字典排序后的起始下标结果

sa数组(后缀数组): 将S的n个后缀从小到大进行排序之后把排好序的后缀的开头位置顺次放入SA
rk数组(名次数组): 名次数组Rank[i]保存的是Suffix(i)在所有后缀中从小到大排列的“名次”
height数组:定义height[i]=suffix(sa[i-1])和suffix(sa[i])的最长公共前缀,也就是排名相邻的两个后缀的最长公共前缀。那么对于j和k,不妨设rank[j]< rank[k],则有以下性质:
suffix(j)和suffix(k)的最长公共前缀为height[rank[j]+1],height[rank[j]+2],height[rank[j]+3],……,height[rank[k]]中的最小值。

常用方法:
单串问题:
1.可重叠最长重复子串:给定一个字符串,求最长重复子串,这两个子串可重叠
重复子串即是两后缀的公共前缀,最长重复子串,等价于两后缀的最长公共前缀的最大值
只需计算height数组,再比较最大值,就是最长重复子串的长度

2.不可重叠最长重复子串:
直接用height数组不能保证两后缀不重叠,可二分答案,进行判定
问题转化为:原串中是否有长度为k的重复子串,按height数组把后缀分组,每组height值都>=k。
若存在至少一组,SAmax - SAmin >=k,则存在长度为k的重复子串

3.最长k次重复子串:求至少出现k次的最长重复子串,且k个子串可以重叠
先二分答案,将后缀分成如果组,判断有没有一个组的后缀个数不小于k,若有,则存在k个相同的子串满足条件
反之,不存在

4.不同子串的个数:
即对n-sa[i]+1-height[i]求和

双串问题:
1.最长公共子串:给定两个串,求这两个串的最长公共子串
先将两个串拼接在一起,形成A&B的形式,$为分隔符,小于所有字母。再求出新串的后缀数组及height
求排名相邻,原来不在同一个字符串的height值的最大值

2.长度小于k的公共子串个数:求两个串中,长度不小于k的公共子串个数,可以相同
先将两个串拼接,按height值分组后,统计每组中后缀之间的最长公共前缀和
扫描一遍,没遇到一个b的后缀就统计与前面a的后缀能产生多少个长度不小于k的公共子串
a的后缀用一个单调栈维护,再对a的后缀与前面b的后缀也做同样的计算

多串问题:
1.其它串没有的子串:问a串中有多少种字符串集合B中没有的连续子串
先将a串和其它子串拼接,求一遍总的子串个数,再减去a串与集合B相连的子串个数

2.多串的最长公共子串:
将n个字符串拼接,二分答案,将后缀按height值分成若干组,判断是否存在一组后缀属于n个字符串

3.不少于k个串的最长子串
将n个字符串拼接,求后缀数组,二分答案,将后缀按height值分成若干组
判断每组的后缀是否出现在不小于k个的原串中

4.每个串中至少出现2次且不重叠的子串个数:
将所有串拼接,二分答案,按height值分组,若某一组存在每个串至少出现2次,则满足

5.出现或反转后出现在每个字符串的最长子串:
先将每个字符串反转,在将反转后的与原来的一起全部拼接,求后缀数组。
二分答案,将后缀分组,判断时看是否有一组后缀在每个原来的串或反转后的串中出现

构建后缀数组和height,倍增法O(nlogn),求出现次数大于等于k次的最长子串长度
 

八.后缀自动机

求出现k次(或大于k次,或k1~k2次)的子串个数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值