首页 > 其他 > 详细

后缀数组模版

时间:2014-01-22 22:03:50      阅读:388      评论:0      收藏:0      [点我收藏+]

----by kuangbin

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <set>
#define N 100005
#define M 105
using namespace std;
#define rank Rank
/*
* 后缀数组
* DC3算法,复杂度O(n)
* 所有的相关数组都要开三倍
*/
const int MAXN=20010;
int rank[MAXN],height[MAXN];
#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
int wa[MAXN*3],wb[MAXN*3],wv[MAXN*3],wss[MAXN*3];
int c0(int *r,int a,int b)
{
	return r[a] == r[b] && r[a+1] == r[b+1] && r[a+2] == r[b+2];
}
int c12(int k,int *r,int a,int b)
{
	if(k == 2)
		return r[a] < r[b] || ( r[a] == r[b] && c12(1,r,a+1,b+1) );
	else return r[a] < r[b] || ( r[a] == r[b] && wv[a+1] < wv[b+1] );
}
void sort(int *r,int *a,int *b,int n,int m)
{
	int i;
	for(i = 0;i < n;i++)wv[i] = r[a[i]];
	for(i = 0;i < m;i++)wss[i] = 0;
	for(i = 0;i < n;i++)wss[wv[i]]++;
	for(i = 1;i < m;i++)wss[i] += wss[i-1];
	for(i = n-1;i >= 0;i--)
		b[--wss[wv[i]]] = a[i];
}
void dc3(int *r,int *sa,int n,int m)
{
	int i, j, *rn = r + n;
	int *san = sa + n, ta = 0, tb = (n+1)/3, tbc = 0, p;
	r[n] = r[n+1] = 0;
	for(i = 0;i < n;i++)if(i %3 != 0)wa[tbc++] = i;
	sort(r + 2, wa, wb, tbc, m);
	sort(r + 1, wb, wa, tbc, m);
	sort(r, wa, wb, tbc, m);
	for(p = 1, rn[F(wb[0])] = 0, i = 1;i < tbc;i++)
		rn[F(wb[i])] = c0(r, wb[i-1], wb[i]) ? p - 1 : p++;
	if(p < tbc)dc3(rn,san,tbc,p);
	else for(i = 0;i < tbc;i++)san[rn[i]] = i;
	for(i = 0;i < tbc;i++) if(san[i] < tb)wb[ta++] = san[i] * 3;
	if(n % 3 == 1)wb[ta++] = n - 1;
	sort(r, wb, wa, ta, m);
	for(i = 0;i < tbc;i++)wv[wb[i] = G(san[i])] = i;
	for(i = 0, j = 0, p = 0;i < ta && j < tbc;p++)
		sa[p] = c12(wb[j] % 3, r, wa[i], wb[j]) ? wa[i++] : wb[j++];
	for(;i < ta;p++)sa[p] = wa[i++];
	for(;j < tbc;p++)sa[p] = wb[j++];
}
//str和sa也要三倍
void da(int str[],int sa[],int rank[],int height[],int n,int m) // r, sa, rank, height, strlen(str)+1, 128
{
	for(int i = n;i < n*3;i++)
		str[i] = 0;
	dc3(str, sa, n+1, m);
	int i,j,k = 0;
	for(i = 0;i <= n;i++)rank[sa[i]] = i;
	for(i = 0;i < n; i++)
	{
		if(k) k--;
		j = sa[rank[i]-1];
		while(str[i+k] == str[j+k]) k++;
		height[rank[i]] = k;
	}
}

char str[MAXN];
int r[MAXN];	//把str数组复制一遍,并在结尾+0
int sa[MAXN];	//[1-len]



 

后缀数组模版

原文:http://blog.csdn.net/acmmmm/article/details/18656121

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!