zoukankan      html  css  js  c++  java
  • 【文文殿下】后缀自动机(SAM)求最长公共子串的方法

    首先,在A 串上建立一个SAM,然后用B串在上面跑。具体跑的方法是:

    从根节点开始,建立一个指针 p ,指着B串的开头,同步移动指针,沿着SAM的边移动,如果可以移动(即存在边)那么万事皆好,直接len++就好,但是,如果无法继续转移(失配了),那么,我们考虑跳回其父节点,因为其父节点的Right集是当前状态的真超集,那么其父节点状态所代表的字符串的集合中的任意一个字符串,都是当前状态所代表的字符串集合中的正在匹配的字符串(会不会一定是最长串?)的后缀,所以,有一个贪心的思想:父节点状态中的最长串一定是合法的,我们顺着父节点找上去,一定最终可以找到一个节点允许下一个字符转移,或者找到了0号节点。

    第一种情况:找到了一个合适的状态,那么大家都好,直接从这里继续跑,同时把len强制更新为Max(G)(这里要不要+1有一点争论,如果+1,那么接下来跑串时,之前失配的那个字符可能对答案贡献了2次?,因为跑到下一个状态时,是沿着之前那个失配字符的那条边跑的,这会导致len++,所以我认为这里不应该+1),因为我们之前跑的那个已经成功的串,这里一定取那个已经匹配了的最长后缀,然后接下来继续跑串。

    第二中情况:我们无法找到一个状态拥有x这条边,就算是根节点也没有这个边,说明模板串出现了一个原串中没有出现的字符,我们强制更新当前状态为根节点,然后把指针p从字符x挪过去,从他的下一个字符开始匹配。

    但实际上,我们没必要考虑第二种情况:我们先预处理模板串,把原串中不存在的字符去掉,把模板串分成一个个小的模板串,然后从最大的模板串跑匹配,记录当前答案,这里有一个显而易见的优化:如果即将跑的模板串长度低于全局答案,那么我们跳过这个模板串。

    事实上,len不应该设为Max(G)+1

  • 相关阅读:
    spring
    google-c-style
    process想停就停,真爽
    mytop
    Java 图片设置圆角(设置边框,旁白)
    当setTimeout遇到闭包
    FreeMarker辅助
    ImageIO.wtrie生成jpg图片质量损失方案:BufferedImage生成jpg图片文件流
    从BufferedImage到InputStream,实现绘图后进行下载(生成二维码图片并下载)
    使用Javascript 实现类
  • 原文地址:https://www.cnblogs.com/Syameimaru/p/9338969.html
Copyright © 2011-2022 走看看