zoukankan      html  css  js  c++  java
  • BZOJ 2946: [Poi2000]公共串( 后缀自动机 )

    一个串建后缀自动机, 其他串在上面跑, 然后用当前串跑的去更新全部

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

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
     
    using namespace std;
     
    const int maxn = 10009;
    const int n = 26;
     
    char s[maxn];
     
    struct Node {
    Node *fa, *ch[n];
    int len, mx, ans;
    } pool[maxn], *pt, *Root, *Last;
     
    Node* newNode(int l) {
    pt->fa = NULL;
    pt->ans = pt->len = l;
    memset(pt->ch, 0, sizeof pt->ch);
    return pt++;
    }
     
    void InitSAM() {
    pt = pool;
    Last = Root = 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(q->len == p->len + 1)
    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;
    }
     
    inline void upd(int &x, int t) {
    if(t > x)
    x = t;
    }
     
    int main() {
    InitSAM();
    int T; scanf("%d", &T);
    scanf("%s", s);
    for(int i = 0, n = strlen(s); i < n; i++) Extend(s[i] - 'a');
    if(T == 1) {
    printf("%d ", strlen(s));
    return 0;
    }
    while(--T) {
    for(Node *o = pt; o-- != pool; ) o->mx = 0;
    scanf("%s", s);
    Node *t = Root;
    for(int i = 0, n = strlen(s), lth = 0; i < n; i++) {
    int c = s[i] - 'a';
    if(t->ch[c])
    upd((t = t->ch[c])->mx,++lth);
    else {
    for(; t && !t->ch[c]; t = t->fa);
    if(!t) {
    lth = 0; t = Root;
    } else {
    lth = t->len + 1;
    upd((t = t->ch[c])->mx, lth);
    }
    }
    }
    for(Node *o = pt; o-- != pool; )
    if(o->fa) upd(o->fa->mx, o->mx);
    for(Node *o = pt; o-- != pool; )
    o->ans = min(o->ans, o->mx);
    }
    int ans = 0;
    for(Node *o = pt; o-- != pool; upd(ans, o->ans));
    printf("%d ", ans);
    return 0;
    }

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

    2946: [Poi2000]公共串

    Time Limit: 3 Sec  Memory Limit: 128 MB
    Submit: 327  Solved: 143
    [Submit][Status][Discuss]

    Description

     
           给出几个由小写字母构成的单词,求它们最长的公共子串的长度。
    任务:
    l        读入单词
    l        计算最长公共子串的长度
    l        输出结果
     

    Input

     
    文件的第一行是整数 n1<=n<=5,表示单词的数量。接下来n行每行一个单词,只由小写字母组成,单词的长度至少为1,最大为2000
     

    Output

    仅一行,一个整数,最长公共子串的长度。
     

    Sample Input

    3
    abcb
    bca
    acbc

    Sample Output

    HINT

    Source

  • 相关阅读:
    uip源码剖析【一】——【网络层】ARP解读
    MySql字符编码详解
    51单片机+uip实战
    dos中如何查找一个字符串是否包含在某个文件中,如果有则将该文件名输出
    Full TCP/IP for 8Bit Architectures 阅读
    个人PKM之路
    Overlooked Essentials For Optimizing Code
    Would it be faster to batch SetVertex/PixelShaderConstant calls?
    2D Skinned Mesh(3D的完全翻版 带旋转)
    The difference between d8&d9's constants def in asm shaders
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/5033974.html
Copyright © 2011-2022 走看看