算法很美——第四章:字符串
题10补充、题11、hash、滚动哈希、KMP:最短摘要的生成未完成
- 题1:判断字符串有无重复字符
思路:辅助数组计数 - 题2:翻转字符串
- 题3:变形词问题
变形词:字符串A能变形为字符串B
思路:字符串A辅助数组计数,B从辅助数组减 - 题4:替换字符串中的空格
- 题5:压缩字符串
- 题6:判断两字符串字符集是否相等
- 题7:旋转词
思路:旋转词首先判断长度相等,然后判断两个A拼接后是否包含B - 题8:将字符串按单词翻转
- 题9:去掉字符串中连续出现的k个0
- 题10:回文串
- 补充:第七届蓝桥杯——密码脱落
X星球的考古学家发现了一批古代留下来的密码。
这些密码是由A、B、C、D 四种植物的种子串成的序列。
仔细分析发现,这些密码串当初应该是前后对称的(也就是我们说的镜像串)。
由于年代久远,其中许多种子脱落了,因而可能会失去镜像的特征。
你的任务是:
给定一个现在看到的密码串,计算一下从当初的状态,它要至少脱落多少个种子,才可能会变成现在的样子。
输入一行,表示现在看到的密码串(长度不大于1000)
要求输出一个正整数,表示至少脱落了多少个种子。
例如,输入:
ABCBA
则程序应该输出:
0
再例如,输入:
ABECDCBABC
则程序应该输出:
3
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 1000ms - 题11:最短摘要的生成
思路:双指针(尺取法)
开始找到第一个摘要单词,记录出现位置i,往下找直到包括所有摘要单词,记录最后一个单词出现位置,更新最短摘要,i移动到下一个摘要单词,判断i,j间是否出现所有摘要单词,出现,则更新最短摘要,未出现,则更新j位置,直到字符串结束
字符串匹配
-
朴素算法:O(m*n)
-
哈希算法:O(m*n)
求目标串hash值,及原串中所有可能子串的hash值,进行比较
求hash值相当于求key进制数:假设n=3,b[0]*(key^2)+b[1]*key+b[2],等价于(b[0]*key+b[1])*key+b[2] -
RabinKarp:改良哈希算法为滚动哈希——O(n+m)
将分别求每一个可能子串的hash值改为(上一个的hash值加上最后一个减去第一个)
然而,hash值相同未必表示两字符串一定相同,可能两字符串差异很大,但由于哈希冲突,导致两字符串hash值相同,为避免这一情况的出现,可在hash值相同的情况下,再用朴素算法确认两字符串相同 -
KMP:O(m+n)
-
应用后缀数组进行模式匹配
后缀数组:串的所有后缀子串按字典序排序后,在数组中记录后缀的起始下标
与后缀数组相似,有rank数组,是将后缀数组值与下标对换
原理:所有子串都是某个后缀的前缀
由此,完成字符串的模式匹配
由于数组有序,可采用二分查找
截取和模式串等长后缀子串进行比较
复杂度:O(nlogm),当m(原串长度)过大时,与KMP相比后缀数组更有优势
求后缀数组:排序即可,O(nnlogn)
后缀子串和起始下标可用结构体
求后缀数组的优化:倍增法——O(nlognlogn)
倍增法:k=1,一个字符,排序,得到sa,rk
k=2,两个字符,用rk快速进行排序,得到sa,rk
k=4
k=8
……
改进:每次不再更新suff,+图2