• SPOJ1812 LCS2


    SPOJ1812 LCS2


    题意:给n个串,求最长公共子串

    做法:对第一个串建(SAM),拿剩余的串类似于求(LCS)的在上面跑,对于当前这个串,求出可以到达每个状态的最长子串长度,然后,每个状态对每个串的匹配取最小值,最后取最大值就是答案。现在考虑如何求到达每个状态的最长子串长度,我们先类似于求(LCS)的,维护一个(now)表示当前状态,(l)表示匹配的长度,在跑的过程中更新每个状态的最长子串长度,显然更新完一个状态后,这个状态的所有有缀,即(parent)树上,这个状态的祖先们,都应该更新,于是在匹配都结束后,倒着拓扑序更新完所有的状态。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    
    const int N = 100010;
    typedef long long ll;
    
    using namespace std;
    
    struct SAM {
        int n, step[N<<1], fa[N<<1], ch[N<<1][26], tmp[N<<1], num[N<<1], mn[N<<1], last, root, cnt, A[N];
        char s[N];
        void init() {
            memset(mn, 0x3f, sizeof(mn));
            cnt = 0; last = root = ++ cnt;
        }
    
        void add(int x) {
            int p = last, np = ++cnt;
            step[np] = step[p] + 1;
            while(p && !ch[p][x]) ch[p][x] = np, p = fa[p];
    
            if(!p) fa[np] = root;
            else {
                int q = ch[p][x];
                if(step[q] == step[p] + 1) fa[np] = q;
                else {
                    int nq = ++ cnt;
                    fa[nq] = fa[q]; memcpy(ch[nq], ch[q], sizeof(ch[q]));
                    fa[q] = fa[np] = nq;  step[nq] = step[p] + 1;
                    while(p && ch[p][x] == q) ch[p][x] = nq, p = fa[p];
                }
            }
            last = np;
        }
        void calright() {
            for(int i = 1; i <= cnt; ++i) ++ A[step[i]];
            for(int i = 1; i <= n; ++i) A[i] += A[i-1];
            for(int i = cnt; i; --i) num[A[step[i]]--] = i;
        }
        void run() {
            scanf(" %s",s+1), n = strlen(s + 1);
            for(int i = 1; i <= n; ++i) add(s[i]-'a');
            calright();
            memset(mn, 0x3f, sizeof(mn));
        }
    
        void solve(char b[]) {
            memset(tmp,0,sizeof(tmp));
            int m = strlen(b+1), now = 1, l = 0;
            for(int i = 1; i <= m; ++i) {
                if(ch[now][b[i] - 'a'])  ++ l, now = ch[now][b[i] - 'a'];
                else {
                    while(now  && !ch[now][b[i] - 'a']) now = fa[now];
                    if(!now) now = 1, l = 0;
                    else l = step[now]+1, now = ch[now][b[i] - 'a'];
                }
                tmp[now] = max(tmp[now], l); /// only update the end
            }
            for(int i = cnt; i; --i) {
                mn[num[i]] = min(mn[num[i]], tmp[num[i]]);
                if( fa[num[i]] && tmp[num[i]] ) tmp[fa[num[i]]] = step[fa[num[i]]];
            }
        }
    
    } Fe;
    
    char str[N];
    
    int main() {
        // freopen("in","r",stdin);
        Fe.init();
        Fe.run();
        while(~ scanf(" %s",str+1)) {
            Fe.solve(str);
        }
        int ans = 0;
        for(int i = 1; i <= Fe.cnt; ++i) ans = max(ans, Fe.mn[i]);
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    数据库操作--获取空数据
    常用的css属性
    有序列表与无序列表
    表格标签table
    Div 块 盒子
    border边框 css属性
    IMG
    html中a标签与img标签
    CSS
    css 网页中如何嵌套style样式?
  • 原文地址:https://www.cnblogs.com/RRRR-wys/p/10200443.html
Copyright © 2020-2023  润新知