HDU 4622 suffix array (for the number of substrings in the interval)

topic link

The meaning of the question: given a string, ask multiple times, and each time you ask to find the number of substrings in an interval. (substrings cannot be the same)

Idea: When calculating the number of strings in the suffix array, it is calculated by traversing the Height array in lexicographical order. So applied to this question, the simplest idea is of course to directly brute force each query (extract the string of each query as a string to get the answer), but the violence is too clumsy (this question can be passed a few times with violence!! !). Recalling the way of counting through the Height array again, there is a very important point - traversing in lexicographical order. Having grasped this, we traverse through the original string and count to get the answer.

C++ code:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2010;

int n;
char s[maxn];
int ch[maxn];
int Sa[maxn];
int Rank[maxn];
int Height[maxn];
int t1[maxn],t2[maxn],c[maxn];

bool cmp( int *r , int a , int b , int l )
{
	return r[a]==r[b]&&r[a+l]==r[b+l];
}

void SA( int m )
{
	n++; int *x=t1,*y=t2;
	for ( int i=0 ; i<m ; i++ ) c[i] = 0;
	for ( int i=0 ; i<n ; i++ ) c[x[i] = ch[i]]++;
	for ( int i=1 ; i<m ; i++ ) c[i] += c[i-1];
	for ( int i=n-1 ; i>=0 ; i-- ) Sa[--c[x[i]]] = i;
	for ( int j=1,p ; j<=n ; j<<=1 )
	{
		p = 0;
		for ( int i=n-j ; i<n ; i++ ) y[p++] = i;
		for ( int i=0 ; i<n ; i++ ) if ( Sa[i]>=j ) y[p++] = Sa[i]-j;
		for ( int i=0 ; i<m ; i++ ) c[i] = 0;
		for ( int i=0 ; i<n ; i++ ) c[x[y[i]]]++;
		for ( int i=1 ; i<m ; i++ ) c[i] += c[i-1];
		for ( int i=n-1 ; i>=0 ; i-- ) Sa[--c[x[y[i]]]] = y[i];
		swap( x , y );
		p = 1;
		x [At [0]] = 0;
		for ( int i=1 ; i<n ; i++ )
			x [Sa [i]] = cmp (y, Sa [i-1], Sa [i], j)? p-1: p ++;
		if ( p>=n ) break;
		m = p;	
	}
	for ( int i=0 ; i<n ; i++ ) Rank[Sa[i]] = i;
	n--;
	int l = 0;
	for ( int i=0 ; i<n ; i++ )
	{
		if ( l ) l--;
		int j = In [Rank [i] -1];
		while ( ch[i+l]==ch[j+l] ) l++;
		Height[Rank[i]] = l;
	}
}

int rmq[20][maxn];

void rmq_init()
{
	for ( int i=0 ; i<=n ; i++ ) rmq[0][i] = Height[i];
	for ( int i=1 ; (1<<i)<=n+1 ; i++ )
		for ( int j=0 ; j+(1<<i)<=n+1 ; j++ )
			rmq[i][j] = min( rmq[i-1][j] , rmq[i-1][j+(1<<(i-1))] );  
}

int rmq_query( int l , int r )
{
	int k = 0;
	while ( 1<<(k+1)<=r-l+1 ) k++;
	return min( rmq[k][l] , rmq[k][r-(1<<k)+1] );
}

int slove (int l, int r)
{
	int ans = (r-l+1)*(r-l+2)/2;
	int las = -1;
	for ( int i=1 ; i<=n ; i++ )
	{
		if ( Sa[i]+1<l||Sa[i]+1>r ) continue;
		if ( las==-1 )
		{
			forest = i;
			continue;
		}
		int a = las;
		int b = i;
		int lp = rmq_query( a+1 , b );
		int la = r-Sa [a];
		int lb = r-Sa[b];
		years -= min( lp , min( la , lb ) );
		if ( la<lb||lp<lb ) las = i;
	}
	return ans;
}

intmain()
{
    int T; scanf ( "%d" , &T );
    while ( T-- )
    {
    	scanf ( "%s" , s );
		n = strlen(s);	
		for ( int i=0 ; i<n ; i++ )
			ch[i] = s[i]-'a'+1;
		ch[n] = 0;
		SA (27);
		rmq_init();	
		int Q; scanf ( "%d" , &Q );
		while ( Q-- )
		{
			int l,r; scanf ( "%d%d" , &l , &r );
			printf  ( "%d\n" , slove( l , r ) );
		}
	}
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324811051&siteId=291194637