zoukankan      html  css  js  c++  java
  • poj 2774 Long Long Message 后缀数组LCP理解

    题目链接

    题意:给两个长度不超过1e5的字符串,问两个字符串的连续公共子串最大长度为多少?

    思路:两个字符串连接之后直接后缀数组+LCP,在height中找出max同时满足一左一右即可;

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string.h>
    #include<algorithm>
    #include<map>
    #include<queue>
    #include<vector>
    #include<cmath>
    #include<stdlib.h>
    #include<time.h>
    using namespace std;
    typedef long long ll;
    const int MAXN = 200007;
    char s[MAXN],str[MAXN];
    int sa[MAXN],t[MAXN],t2[MAXN],c[MAXN],n;
    void build_sa(int m,int n) // m为字符ASCII码的最大值+1;n = strlen(s) + 1;
    {
        int i,*x = t, *y = t2;
        for(i = 0;i < m; i++) c[i] = 0;
        for(i = 0;i < n; i++) c[x[i] = s[i]]++;
        for(i = 1;i < m; i++) c[i] += c[i-1];
        for(i = n - 1;i >= 0; i--) sa[--c[x[i]]] = i;
        for(int k = 1;k <= n;k <<= 1){
            int p = 0;
            for(i = n - k;i < n;i++) y[p++] = i;
            for(i = 0;i < n;i++) if(sa[i] >= k) y[p++] = sa[i] - k;
    
            for(i = 0;i < m;i++) c[i] = 0;
            for(i = 0;i < n;i++) c[x[y[i]]]++;
            for(i = 1;i < m;i++) c[i] += c[i-1];
            for(i = n - 1;i >= 0;i--) sa[--c[x[y[i]]]] = y[i];
    
            swap(x,y);
            x[sa[0]] = 0;// 将字符彻底转变为序号;
            for(i = 1,p = 1;i < n;i++)
                x[sa[i]] = y[sa[i]] == y[sa[i-1]] && y[sa[i]+k] == y[sa[i-1]+k]?p-1:p++;
            if(p >= n) break;
            m = p;
        }
    }
    int rk[MAXN],height[MAXN];
    void getHeight()
    {
        int i,j,k = 0;
        for(i = 1;i <= n;i++) rk[sa[i]] = i; // rk[i]:后缀i在sa[]中的下标
        for(i = 0;i < n;i++){
            if(k) k--;
            if(rk[i] == 0) continue;
            j = sa[rk[i] - 1];
            while(i+k<n && j+k<n && s[i+k] == s[j+k]) k++;
            height[rk[i]] = k; // h[i] = height[rk[i]]; h[i] >= h[i-1] - 1;
        }
    }
    int main()
    {
        while(scanf("%s%s",s,str) == 2){
            int len = strlen(s);
            s[len] = '#';s[len+1] = '';
            strcat(s,str);
            n = strlen(s);
            s[n] = '#';
            build_sa('z'+1,n+1);
            getHeight();
            int ans = -1;
            for(int i = 2;i <= n;i++)
                if(height[i] > ans && ((sa[i] < len && sa[i-1] > len) || (sa[i] > len && sa[i-1] < len)))
                    ans = height[i];
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    DAT批处理文件语法
    TreeView控件问题汇总
    windows xp home安装iis
    【Vegas原创】网站计数器(asp)
    转载:shell python脚本互调
    转载:linux的文件属性和权限学习——分析ls命令结果
    python 正则表达式匹配中文
    Python正则表达式
    linux命令备份
    移植算法编译环境到linux【redhat9.0如何显示汉字】
  • 原文地址:https://www.cnblogs.com/hxer/p/5376647.html
Copyright © 2011-2022 走看看