HDU 1403 Suffix Array

/***********************************************************************************
     用Gvim写的, 解法就是求出后缀数组后,算h值最大,并且在'#'两侧的两个串 
***********************************************************************************/
#include <iostream>
#include <functional>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;

#define L(x) ((x) << 1)
#define R(x) ((x) << 1 | 1)
//#define ONLINE_JUDGE

typedef double LF;

const LF eps = 10e-6;

const int MAXN = 2000005;  //the max length of string
const int MAXC = 128;     //the max value of a character

char ss[MAXN], ch[MAXN];
int wa[MAXN], wb[MAXN], wv[MAXN], wc[MAXC], dp[MAXN][22];   //!!!notice wc
int rk[MAXN],h[MAXN], r[MAXN * 3], sa[MAXN * 3];
int inc[22];

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(2 == k)
	{
		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];
	}
}
inline int F(int x, int tb)
{
	return x / 3 + (1 == x % 3 ? 0 : tb);
}
inline int G(int x, int tb)
{
	return x < tb ? x * 3 + 1 : (x - tb) * 3 + 2;
}
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++)
	 {
		 wc[i] = 0;
	 }
	 for(i = 0; i < n; i++)
	 {
		 wc[ wv[i] ]++;
	 }
     for(i = 1; i < m; i++)
	 {
		 wc[i] += wc[i - 1];
	 }
     for(i = n - 1; i >= 0; i--)
	 {
		 b[ --wc[ wv[i] ] ] = a[i];
	 }
     return;
}
void dc3(int *r, int *sa, int n, int m)
{
     int i, j, *rn = r + n, *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], tb) ] = 0, i = 1; i < tbc; i++)
	 {
		rn[ F(wb[i], tb) ] = 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(1 == n % 3)
	 {
		 wb[ta++] = n - 1;
	 }
     sort(r, wb, wa, ta, m);
     for(i = 0; i < tbc; i++)
	 {
		 wv[ wb[i] = G(san[i], tb) ] = 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++];
	 }
     return;
}
void calheight(int *r, int *sa, int n)
{
	for(int i = 0; i < n; ++i)
	{
		rk[ sa[i] ] = i;
	}
	for(int i = 0, k = 0; i < n; ++i)
	{
		if(rk[i] == n - 1)
		{
			h[ rk[i] ] = k = 0;
		}
		else
		{
			if(k > 0)
			{
				--k;
			}
			int j = sa[ rk[i] + 1 ];
			while(r[i + k] == r[j + k])
			{
				++k;
			}
			h[ rk[i] ] = k;
		}
	}
	return ;
}
void test(int n)
{
	for(int i = 0; i < n; ++i)
	{
		printf("%d %d %d %d\n", i, sa[i], rk[i], h[i]);
	}
	return ;
}
void preprocess()
{
	inc[0] = 1;
	for(int i = 1; i < 22; ++i)
	{
		inc[i] = inc[i - 1] << 1;
	}
	return ;
}
void initRMQ(int ind)
{
	int cap = static_cast<int>( log(ind + 0.0) / log(2.0) ), mid;
	for(int i = 0; i < ind; ++i)
	{
		dp[i][0] = h[i];
	}
	for(int j = 1; j <= cap; ++j)
	{
		for(int i = 0; i + inc[j] - 1 < ind; ++i)
		{
			mid = i + inc[j - 1];
			dp[i][j] = min(dp[i][j - 1], dp[mid][j - 1]);
		}
	}
	return ;
}
int query(int x, int y) //query the minimum number between the range of h[x, y];
{
	int k = static_cast<int>( log(y - x + 1.0) / log(2.0) );
	return min(dp[x][k], dp[y - inc[k] + 1][k]);
}
void ace()
{
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
#endif
	int n, m;
	int maxi;
	while (gets(ss))
	{
		gets(ch);
		m = strlen(ss);
		ss[m++] = '#';
		ss[m++] = '\0';
		strcat(ss, ch);
		n = strlen(ss);
		ss[n++] = '\0';
		for (int i = 0; i < n; ++i)
		{
			r[i] = ss[i];
		}
		dc3(r, sa, n, MAXC);
		calheight(r, sa, n);
		maxi = 0;
		for (int i = 0; i < n - 1; ++i)
		{
			if (h[i] > maxi)
			{
				if (sa[i] < m && sa[i + 1] > m || sa[i + 1] < m && sa[i] > m)
				{
					maxi = h[i];
				}
			}
		}
		printf("%d\n", maxi);
	}
	return ;
}
int main()
{
	preprocess();
	ace();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值