zoukankan      html  css  js  c++  java
  • [复习]字符串

    [复习]字符串

    纯复习内容,内容比较粗糙。

    字符串哈希

    最基本的东西,一般而言并不太需要注意哈希被卡的问题。
    个人比较习惯的是单哈希、自然溢出。偶尔会使用多模数哈希,但还是用自然溢出。
    可以用来干的事情:快速判断两个串是否相等,判断回文串等。
    比较容易实现,不多写了。

    最小循环表示法

    (lun)讲过了好多次了嗷。。。。
    这个东西是啥?参考一道题目【洛谷1368/BZOJ2882】工艺
    显然存在一个直接构建(SAM)然后按照字典序跑的做法。
    这里有个简单的做法:定义两个指针(i,j)。初始时(i=1,j=2)
    然后两个指针不断向后匹配,直到扫到两个字符不相等,假设前面相等的长度为(k)
    如果(S[i+k]<S[j+k]),那么显然(j)在这一段之间一直不优,所以令(j=j+k)。否则(i=i+k)
    如果做完上述操作之后两个数相等,则强制一个向后移动即可。

    (KMP)算法

    很久以前写的博客
    重新谈谈。
    (KMP)(next)数字到底是啥呢?(border)。即前缀等于后缀。
    (next)的含义就是以当前位置结尾的最长(border)
    知道了这个那么(next)数组很容易求,假设当前要求的结尾位置为(i)。那么它可能达到的最长(border)(next[i-1]+1),如果可行就做完了。否则只能找(i-1)(border)的最长(border)了,那么就循环处理。最后的特殊情况下(border)可以为(0)
    利用(next)匹配求解答案的时候类似,一旦匹配不上就考虑能否从(border)位置开始匹配。

    (AC)自动机

    显然原来也是写过的
    再来口胡一遍。
    AC自动机可以理解为是(KMP)的多串版本。
    大致的做法是把所有串构建(Trie),定义(fail)指针表示当前节点表示的串中的在(Trie)树上的最长(border)的位置。这样子每次失配的时候直接暴跳(fail)即可。
    (fail)指针的构建方法是(bfs)
    一般而言会有两种不同的(AC)自动机,一种就是最普通的,另外一种是(Trie)图。(Trie)图是所有转移即目标节点构成的图。如果需要在(AC)自动机上面进行(dp)相关操作,(Trie)图是更加合适的选择。

    然后大概归类一下(AC)自动机的相关题目类型:
    首先是纯匹配类型的,完全就是看自己对于(AC)自动机的理解,比如这题、还有这题。这类题目很多,专注于对于(AC)自动机的理解是关键。

    第二类是(AC)自动机上面(dp)。而(dp)的问题一般是一些串不能出现在答案串中的方案数,或是必须出现在答案串中的方案数之类的。做法就是构建(Trie)图,然后在上面匹配。如果是不能出现,那就是有些点不能被访问到,如果是必须出现,那么就状压记录串的出现情况。转移沿着(Trie)图走就行了,并且如果串长之和很小还可以矩乘。题目随便找几道吧。这个这个这个

    第三类是和(fail)树相关的东西,这一类单独拿出来是因为后面的(SAM)(PAM)都有这一类的问题。主要是这题。利用(fail)树加上一些统计子树内询问的方法来解决问题。

    其他的还有一些奇怪的东西,比如二进制分组+(AC)自动机之类的,这里就不提及了。

    (manacher)

    原来都写过啊
    维护回文中心,利用回文的形式来快速求解。
    代码和思想都比较简单,用途不是很多,就不讲了。

    后缀数组

    戳这里
    按照二元组的倍增排序。
    后缀数组能够做的,(SAM)基本都能做,当然也有些东西(SAM)做起来没那么方便。
    所以(SA)还是要会的。

    为了复习随手写了道题目戳这里

    回文树

    似乎回文树就是回文自动机吧?原来也写过QwQ
    关于回文串的一些计数问题,回文树和(manacher)各有利弊。回文树求出来的是以当前位置结尾的回文后缀的个数,而(manacher)求出来的是每个回文中心能够延伸出去的回文半径。用哪个因题而异。
    是在是找不到太多很有意义的题目。
    不过有一道和回文树性质相关的题目。【CF932G】
    给回文树中每个节点定义一个(dif),表示其和父亲的(len)的差。
    定义(anc)表示所有祖先中,第一个与其(dif)不相同的祖先。
    可以证明把当前点到根节点的所有(dif)拿下来一定是一段段的等差数列。并且每个点如果沿着(anc)走到达根节点的次数不会超过(log)次。对于沿着回文树(fail)树上的(dp)转移,可以利用上述性质优化。
    这个玩意支持前端插入后端插入,前端删除,后端删除,但是不常见,所以不太会。

    后缀自动机

    戳这里
    板子什么的背背就好了。但是每个节点表示的是什么,性质之类的,一定要记牢。
    毕竟这个玩意的运用太广了。
    然后如果只要求解(right)集合的大小的话,拓扑序向上合并就好了。
    如果要求(right)集合的话,线段树合并维护。
    还有如果要支持动态维护(right)集合大小的操作的话可以(LCT),题目似乎是【BZOJ2555】
    还可以套上各种各样的东西。
    还有就是两个串的(lcp)就是他们在(SAM)上所代表的节点在(parent)树上的(LCA)(len)
    主要就这些吧。
    这里的变化还是挺多的。

  • 相关阅读:
    Angularjs中文教程
    IE兼容性 css处理常见
    手写画板实现并转化成图片
    canvas 最基本简单的示例
    凡科 网站地址
    IOS学习之路二十二(UIAlertView获得文本框内容及添加北京图片)
    IOS学习之路十四(用TableView做的新闻客户端展示页面)
    IOS开发之路二十一(UIWebView加载本地html)
    iOS学习之路十三(动态调整UITableViewCell的高度)
    IOS学习之路十二(UITableView下拉刷新页面)
  • 原文地址:https://www.cnblogs.com/cjyyb/p/10185074.html
Copyright © 2011-2022 走看看