zoukankan      html  css  js  c++  java
  • spoj

    Longest Common Substring

    题意

    求两个串的最长公共子串。

    分析

    第一个串建后缀自动机,第二个串在自动机上跑,对于自动机上的结点(状态)而言,它所代表的最大长度为根结点到当前结点的长度,而它的前继结点的串一定是这个结点串的后缀串(或空串)。
    匹配过程中一旦失配,自动机上的结点找它的前继结点,继续向后匹配即可。

    code

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 250005;
    char s[MAXN];
    
    /* 性质:
    ① 从root到任意结点p的每条路径上的字符组成的字符串,都是当前串t的子串
    ② 因为满足性质一,所以如果当前结点p是可以接收新后缀的结点,那么从root到任意结点p的每条路径上的字符组成的字符串,都是必定是当前串t的后缀
    ③ 如果结点p可以接收新的后缀,那么p的fa指向的结点也可以接收后缀,反过来就不行
    从 root 出发的任何子串最终都会到达一个合法状态,而非子串最终都会“无路可走”
    */
    struct SAM {
        int ch[MAXN << 1][26];
        int fa[MAXN << 1]; // 前继结点,如果当前结点可以接受某个后缀那么它的前继结点也可以接受
        int len[MAXN << 1]; // 从根结点到该结点的最大距离,这个状态(结点)代表的串长度区间 (len[fa], len]
        int cnt, last;
        void init() {
            memset(ch, 0, sizeof ch);
            memset(fa, 0, sizeof fa);
            last = cnt = 1; // root节点为 1 ,所以添加的字符从 2 开始
        }
        void add(int c) {
            int p = last, np = last = ++cnt;
            len[np] = len[p] + 1;
            while(!ch[p][c] && p) {
                ch[p][c] = np;
                p = fa[p];
            }
            if(p == 0) fa[np] = 1;
            else {
                int q = ch[p][c];
                if(len[p] + 1 == len[q]) { // p、q之间无其他结点
                    fa[np] = q;
                } else { // np的加入导致前面某个结点的状态发生改变
                    int nq = ++cnt;
                    len[nq] = len[p] + 1;
                    memcpy(ch[nq], ch[q], sizeof ch[q]);
                    fa[nq] = fa[q];
                    fa[q] = fa[np] = nq;
                    while(ch[p][c] == q && p) {
                        ch[p][c] = nq;
                        p = fa[p];
                    }
                }
            }
        }
    } sam;
    
    int main() {
        scanf("%s", s);
        int len = strlen(s);
        sam.init();
        for(int i = 0; i < len; i++) {
            sam.add(s[i] - 'a');
        }
        scanf("%s", s);
        len = strlen(s);
        int p = 1;
        int ans = 0;
        int c = 0;
        for(int i = 0; i < len; ) {
            while(sam.ch[p][s[i] - 'a']) {
                p = sam.ch[p][s[i] - 'a'];
                i++;
                c++;
            }
            ans = max(ans, c);
            if(!c) i++;
            else {
                p = sam.fa[p];
                c = sam.len[p];
            }
        }
        printf("%d
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    凤凰网面试经历——钢管舞也算精英文化吗
    立此为证:豆瓣要做电影数字发行了(2010818)
    Officially GoldenGate was purchased by oracle in October 1, 2009
    11gR2新特性:Heavy swapping observed on system in last 5 mins.
    Oracle BMW Racing sailing vessel帆船图
    Know more about CBO Index Cost
    Samsung Epic 4G 图文介绍
    Oracle Exalogic X22 HalfRack DiagramExaloic半配图
    Java 编程下线程的生命周期
    Android 编程组件Fragments 的生命周期与 Activity 的生命周期之间的关系
  • 原文地址:https://www.cnblogs.com/ftae/p/7430097.html
Copyright © 2011-2022 走看看