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

后缀数组

时间:2015-07-25 15:10:42      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:

在夏令营期间学习了作为一个字符串处理神器的后缀数组。

 

bzoj1031 JSOI字符加密Cipher

题目大意:给一个字符串,圈成圆圈,从任意位置断开,组成len个字符串,按字典序升序排序后,输出尾字母。

思路:将字符串加倍后,对所有后缀排序,用后缀数组的思想,O(nlogn),输出的时候只要输出长度>=len的相应位置的字母就可以了。

技术分享
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define maxnode 200005
using namespace std;
int t1[maxnode]={0},t2[maxnode]={0},sa[maxnode]={0},cc[maxnode]={0},n,m=0;
char ss[maxnode];
bool cmp(int *y,int a,int b,int k)
{
    int a2,b2;
    a2= a+k>=n ? -1 : y[a+k];
    b2= b+k>=n ? -1 : y[b+k];
    a=y[a];b=y[b];
    return a==b&&a2==b2;
}
void build()
{
    int i,k,p;int *x=t1;int *y=t2;
    for (i=0;i<m;++i) cc[i]=0;
    for (i=0;i<n;++i) ++cc[x[i]=ss[i]];
    for (i=1;i<m;++i) cc[i]+=cc[i-1];
    for (i=n-1;i>=0;--i) sa[--cc[x[i]]]=i;
    for (k=1;k<=n;k<<=1)
    {
        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) cc[i]=0;
        for (i=0;i<n;++i) ++cc[x[y[i]]];
        for (i=1;i<m;++i) cc[i]+=cc[i-1];
        for (i=n-1;i>=0;--i) sa[--cc[x[y[i]]]]=y[i];
        swap(x,y);m=1;x[sa[0]]=0;
        for (i=1;i<n;++i) x[sa[i]]=cmp(y,sa[i],sa[i-1],k) ? m-1 : m++;
        if (m>=n) break;
    }
}
int main()
{
    int i,n1;
    scanf("%s",&ss);n1=strlen(ss);
    for (i=0;i<n1-1;++i) ss[i+n1]=ss[i]; n=n1*2-1;
    for (i=0;i<n1;++i) m=max(m,(int)ss[i]);
    ++m;build();
    for (i=0;i<n;++i)
      if (sa[i]<n1) printf("%c",ss[sa[i]+n1-1]);
    printf("\n");
}
View Code

 

后缀数组

标签:

原文地址:http://www.cnblogs.com/Rivendell/p/4675879.html

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