zoukankan      html  css  js  c++  java
  • spoj1812 Longest Common Substring II( 后缀自动机 )

     贴个代码...

    ---------------------------------------------------------------------

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
     
    using namespace std;
     
    const int maxn = 200009;
    const int cn = 26;
     
    struct Node {
    Node *fa, *ch[cn];
    int len, Min, Max;
    void upd() {
    Min = min(Min, Max);
    }
    } pool[maxn], *pt, *root, *last;
     
    void upd(Node* &t, int &v) {
    t->Max = max(t->Max, v);
    }
     
    Node* newNode(int v) {
    pt->fa = NULL;
    pt->len = v;
    memset(pt->ch, 0, sizeof pt->ch);
    return pt++;
    }
     
    void SAM_init() {
    pt = pool;
    root = last = newNode(0);
    }
     
    void Extend(int c) {
    Node *p = last, *np = newNode(p->len + 1);
    for(; p && !p->ch[c]; p = p->fa)
    p->ch[c] = np;
    if(!p)
    np->fa = root;
    else {
    Node* q = p->ch[c];
    if(p->len + 1 == q->len)
    np->fa = q;
    else {
    Node* nq = newNode(p->len + 1);
    memcpy(nq->ch, q->ch, sizeof q->ch);
    nq->fa = q->fa;
    q->fa = np->fa = nq;
    for(; p && p->ch[c] == q; p = p->fa)
    p->ch[c] = nq;
    }
    }
    last = np;
    }
     
    char s[maxn];
     
    void SAM_build() {
    scanf("%s", s);
    for(int i = 0, n = strlen(s); i < n; i++)
    Extend(s[i] - 'a');
    }
     
    bool work() {
    if(scanf("%s", s) == -1)
    return false;
    for(Node* t = root; t != pt; t++)
    t->Max = 0;
    int n = strlen(s);
    Node* t = root;
    for(int i = 0, lth = 0; i < n; i++) {
    int c = s[i] - 'a';
    if(t->ch[c])
    upd(t = t->ch[c], ++lth);
    else {
    for(; t && !t->ch[c]; t = t->fa);
    if(!t) 
    t = root, lth = 0;
    else
    lth = t->len + 1, upd(t = t->ch[c], lth);
    }
    }
    for(Node* o = pt; --o != pool; )
    upd(o->fa, o->Max);
    for(Node* o = pt; --o; ) {
    o->upd();
    if(o == pool) break;
    }
    return true;
    }
     
    int main() {
    SAM_init();
    SAM_build();
    for(Node* t = root; t != pt; t++)
    t->Min = t->len;
    while(work());
    int ans = 0;
    for(Node* t = root; t != pt; t++)
    ans = max(ans, t->Min);
    printf("%d ", ans);
    return 0;
    }

    --------------------------------------------------------------------- 

  • 相关阅读:
    线性地址物理地址逻辑地址转换mmu
    C/c++ 宏返回值
    树的子结构
    合并两个排序的链表
    链表中倒数第k个结点
    数值的整数次方
    原码、反码与补码
    二进制中1的个数
    矩形覆盖
    变态跳台阶
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4973027.html
Copyright © 2011-2022 走看看