zoukankan      html  css  js  c++  java
  • poj2774

    题意:给出两个字符串,求最长公共子串的长度。

    分析:一道后缀数组的题,构造后缀数组有两种算法,dc3和倍增,效率分别为O(n)和O(nlogn),但前者的实现较困难。后缀数组构造后获得了3个数组,sa[i]表示所有后缀排序后的排在第i位的后缀,rank[i]表示原串从第i位到结尾的那个后缀在sa中的排名是多少。height[i]表示sa[i]和sa[i + 1]所表示的字符串的最长公共前缀的长度。本题可以利用height来做,先把两个串连接,找最大height。但是记得在把两个字符串连接时加一个特殊字符作分隔。并注意判断两个sa起始位置不在一个串的内部。之所以要加这个分隔符,首先是可以保证我们所求的两个串的起始位置在sa中是相邻的,如果不加入这个分隔符,答案中两个子串在sa中可能中间会出现一些横跨两个字符串的后缀,遇到这种不相邻的情况,需要用height在两串之间的最小值外加复杂的两串是否合法匹配的判断,例如:aaba,abaaba。如果没有判断好可能会出现abaabaaba与abaaba的匹配。而且这样一来求区间内height最小值的复杂度至少是O(nlogn)(用rmq)。

    View Code
    #include <iostream>
    #include
    <cstdlib>
    #include
    <cstring>
    #include
    <cstdio>
    usingnamespace std;

    #define N 200000

    char s[N]; // N > 256
    int n, sa[N], height[N], rank[N], tmp[N], top[N];
    void makesa()
    {
    // O(N * log N)
    int i, j, len, na;
    na
    = (n <256?256 : n);
    memset(top,
    0, na *sizeof(int));
    for (i =0; i < n; i++)
    top[rank[i]
    = s[i] &0xff]++;
    for (i =1; i < na; i++)
    top[i]
    += top[i -1];
    for (i =0; i < n; i++)
    sa[
    --top[rank[i]]] = i;
    for (len =1; len < n; len <<=1)
    {
    for (i =0; i < n; i++)
    {
    j
    = sa[i] - len;
    if (j <0)
    j
    += n;
    tmp[top[rank[j]]
    ++] = j;
    }
    sa[tmp[top[
    0] =0]] = j =0;
    for (i =1; i < n; i++)
    {
    if (rank[tmp[i]] != rank[tmp[i -1]] || rank[tmp[i] + len] != rank[tmp[i -1] + len])
    top[
    ++j] = i;
    sa[tmp[i]]
    = j;
    }
    memcpy(rank, sa, n
    *sizeof(int));
    memcpy(sa, tmp, n
    *sizeof(int));
    if (j >= n -1)
    break;
    }
    }
    void lcp()
    {
    // O(4 * N)
    int i, j, k;
    for (j = rank[height[i = k =0] =0]; i < n -1; i++, k++)
    while (k >=0&& s[i] != s[sa[j -1] + k])
    height[j]
    = (k--), j = rank[sa[j] +1];
    }
    int main()
    {
    // freopen("D:\\t.txt", "r", stdin);
    gets(s);
    int l1 = strlen(s);
    s[l1]
    ='$';
    gets(s
    + l1 +1);
    int len;
    n
    = len = strlen(s);
    n
    ++;
    s[n]
    ='$';
    makesa();
    lcp();
    int ans =0;
    for (int i =0; i < n; i++)
    if ((sa[i] < l1 && sa[i -1] > l1) || (sa[i] > l1 && sa[i -1] < l1))
    if (height[i] > ans)
    ans
    = height[i];
    printf(
    "%d\n", ans);
    return0;
    }
  • 相关阅读:
    ibatis插入正确但查询不出数据的问题
    Java 动态代理机制分析及扩展--转
    java实现插入排序算法 附单元测试源码
    unix基础知识
    作为大数据和云计算学习的一个序吧
    Understanding JVM Internals---不得不转载呀
    回文推理
    java 正则表达式提取html纯文本
    OpenCV功能界面和示例
    【POJ3268】Silver Cow Party 最短
  • 原文地址:https://www.cnblogs.com/rainydays/p/2040993.html
Copyright © 2011-2022 走看看