码迷,mamicode.com
首页 > 编程语言 > 详细

后缀数组小结

时间:2015-09-04 18:32:51      阅读:186      评论:0      收藏:0      [点我收藏+]

标签:

后缀数组又被称为字符串处理神器;

http://blog.csdn.net/xymscau/article/details/8798046 这里讲的非常好

实现rank排名是用到了倍增法和一个比较神奇的计数排序,时间复杂度是nlongn

height[i]存放的是排名第i的后缀与排名第i-1的后缀的最长前缀,

sa[i]存的是排名第i的后缀是第几位开头的

rk[i]存放第i个位置开头的后缀的字典序排名

1.poj2774(后缀数组水题)

题意:给你两串字符,要你找出在这两串字符中都出现过的最长子串.........

思路:先用个分隔符将两个字符串连接起来,再用后缀数组求出height数组的值,找出一个height值最大并且i与i-1的sa值分别在两串字符中就好.....

正确性证明,另一个后缀是i,与它拥有最长公共前缀的的后缀j,我们知道i和j一定排名是相连的。

那么我们将两个字符用空格连接起来之后,如果答案是在i和j这两个位置,如果这两个位置的rank是不相连的,那么设中间有一个值是k,那么显然i与k,或者j与k是一个更优的解。

技术分享
#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;

#define rep(i,n) for(int i = 0;i < n; i++)
using namespace std;
const int size  = 200005,INF = 1<<30;
int rk[size],sa[size],height[size],w[size],wa[size],res[size];
void getSa (int len,int up) {
    int *k = rk,*id = height,*r = res, *cnt = wa;
    rep(i,up) cnt[i] = 0;
    rep(i,len) cnt[k[i] = w[i]]++;
    rep(i,up) cnt[i+1] += cnt[i];
    for(int i = len - 1; i >= 0; i--) {
        sa[--cnt[k[i]]] = i;
    }
    int d = 1,p = 0;
    while(p < len){
        for(int i = len - d; i < len; i++) id[p++] = i;
        rep(i,len)    if(sa[i] >= d) id[p++] = sa[i] - d;
        rep(i,len) r[i] = k[id[i]];
        rep(i,up) cnt[i] = 0;
        rep(i,len) cnt[r[i]]++;
        rep(i,up) cnt[i+1] += cnt[i];
        for(int i = len - 1; i >= 0; i--) {
            sa[--cnt[r[i]]] = id[i];
        }
        swap(k,r);
        p = 0;
        k[sa[0]] = p++;
        rep(i,len-1) {
            if(sa[i]+d < len && sa[i+1]+d <len &&r[sa[i]] == r[sa[i+1]]&& r[sa[i]+d] == r[sa[i+1]+d])
                k[sa[i+1]] = p - 1;
            else k[sa[i+1]] = p++;
        }
        if(p >= len) return ;
        d *= 2,up = p, p = 0;
    }
}
void getHeight(int len) {
    rep(i,len) rk[sa[i]] = i;
    height[0] =  0;
    for(int i = 0,p = 0; i < len - 1; i++) {
        int j = sa[rk[i]-1];
        while(i+p < len&& j+p < len&& w[i+p] == w[j+p]) {
            p++;
        }
        height[rk[i]] = p;
        p = max(0,p - 1);
    }
}
int getSuffix(char s[]) {
    int len = strlen(s),up = 0;
    for(int i = 0; i < len; i++) {
        w[i] = s[i];
        up = max(up,w[i]);
    }
    w[len++] = 0;
    getSa(len,up+1);
    getHeight(len);
    return len;
}const int maxa = 100000*2+1;
char str[maxa];
int main(){
    while(scanf("%s", str)!=EOF){
        int l = strlen(str);
        str[l] =  ;
        scanf("%s", str+l+1);
        getSuffix(str);
        int ans = 0;
        int L = strlen(str);
        for(int i = 1;i < L; i++){
            if((sa[i-1] < l && sa[i] > l) || (sa[i-1] > l && sa[i] < l)){
                ans = max(ans, height[i]);
            }
        }
        printf("%d\n", ans);
    }
}
/*
abcde
bcde
*/
View Code

 

后缀数组小结

标签:

原文地址:http://www.cnblogs.com/icodefive/p/4782060.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!