zoukankan      html  css  js  c++  java
  • 后缀数组 POJ 2217 Secretary

    题目链接

    题意:求两个字符串的最长公共子串

    分析:做法是构造新的串是两个串连接而成,中间用没有出现的字符隔开(因为这样才能保证S的后缀的公共前缀不会跨出一个原有串的范围),即newS = S + '$' + T。对其求sa数组和height数组,取最小值的height[i],且两个后缀串属于不同的字符串。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <string>
    
    typedef long long ll;
    const int N = 1e4 + 5;
    std::string t, str;
    int sa[N<<1], rank[N<<1];
    int height[N<<1];
    int tmp[N<<1];
    
    int n, k;
    bool cmp_sa(int i, int j) {
        if (rank[i] != rank[j]) {
            return rank[i] < rank[j];
        } else {
            int ri = i + k <= n ? rank[i+k] : -1;
            int rj = j + k <= n ? rank[j+k] : -1;
            return ri < rj;
        }
    }
    
    void get_sa(std::string S, int *sa) {
        n = S.length ();
        for (int i=0; i<=n; ++i) {
            sa[i] = i;
            rank[i] = i < n ? (int) S[i] : -1;
        }
        for (k=1; k<=n; k<<=1) {
            std::sort (sa, sa+n+1, cmp_sa);
            tmp[sa[0]] = 0;
            for (int i=1; i<=n; ++i) {
                tmp[sa[i]] = tmp[sa[i-1]] + (cmp_sa (sa[i-1], sa[i]) ? 1 : 0);
            }
            for (int i=0; i<=n; ++i) {
                rank[i] = tmp[i];
            }
        }
    }
    
    void get_height(std::string S, int *sa, int *height) {
        int n = S.length ();
        for (int i=0; i<n; ++i) {
            rank[sa[i]] = i;
        }
        int h = 0;
        height[0] = 0;
        for (int i=0; i<n; ++i) {
            int j = sa[rank[i]-1];
            if (h > 0) {
                h--;
            }
            for (; j+h<n && i+h<n; h++) {
                if (S[j+h] != S[i+h]) {
                    break;
                }
            }
            height[rank[i]-1] = h;
        }
    }
    
    int run(int len1, std::string S) {
        get_sa (S, sa);
        get_height (S, sa, height);
        int ret = 0;
        for (int i=0; i<S.length (); ++i) {
            if ((sa[i]<len1) != (sa[i+1]<len1)) {
                ret = std::max (ret, height[i]);
            }
        }
        return ret;
    }
    
    int main() {
        int T; scanf ("%d", &T);
        getchar ();
        while (T--) {
            getline (std::cin, t);
            str = t;
            int len1 = t.length ();
            getline (std::cin, t);
            str += '$' + t;
            int ans = run (len1, str);
            printf ("Nejdelsi spolecny retezec ma delku %d.
    ", ans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    (没有意义讨论)二元运算符和自加符的深入理解,小心多个++的陷阱
    c语言复杂变量声明(数组、指针、函数)
    bundle对象传送序列化serialization引用时问题
    android异步任务详解 AsynTask
    servlet使用get方法传送中文参数
    服务器2
    windows server 2003 网站无法访问,重启iis也不行。重启系统解决了。
    得到本周第一天
    JS时间大全
    树状侧边栏
  • 原文地址:https://www.cnblogs.com/Running-Time/p/5448819.html
Copyright © 2011-2022 走看看