hdu3948(后缀数组)

题意:给一串字符,需要你求不相同的回文子串个数.......

同ural1297,链接:http://www.cnblogs.com/ziyi--caolu/archive/2013/06/09/3129877.html

#include<iostream>

#include<stdio.h>

#include<string.h>

using namespace std;

#define maxn 210000

#define max(x,y) x>y? x:y

#define min(x,y) x>y? y:x

int dp[maxn][32],log2[maxn];

int wa[maxn],wb[maxn],wsf[maxn],wv[maxn],sa[maxn];

int rank[maxn],height[maxn],s[maxn];

char str[maxn];

int cmp(int *r,int a,int b,int k)

{

	return r[a]==r[b]&&r[a+k]==r[b+k];

}

void getsa(int *r,int *sa,int n,int m)

{

	int i,j,p,*x=wa,*y=wb,*t;

	for(i=0;i<m;i++)  wsf[i]=0;

	for(i=0;i<n;i++)  wsf[x[i]=r[i]]++;

	for(i=1;i<m;i++)  wsf[i]+=wsf[i-1];

	for(i=n-1;i>=0;i--)  sa[--wsf[x[i]]]=i;

	p=1;

	j=1;

	for(;p<n;j*=2,m=p)

	{

		for(p=0,i=n-j;i<n;i++)  y[p++]=i;

		for(i=0;i<n;i++)  if(sa[i]>=j)  y[p++]=sa[i]-j;

		for(i=0;i<n;i++)  wv[i]=x[y[i]];

		for(i=0;i<m;i++)  wsf[i]=0;

		for(i=0;i<n;i++)  wsf[wv[i]]++;

		for(i=1;i<m;i++)  wsf[i]+=wsf[i-1];

		for(i=n-1;i>=0;i--)  sa[--wsf[wv[i]]]=y[i];

		t=x;

		x=y;

		y=t;

		x[sa[0]]=0;

		for(p=1,i=1;i<n;i++)

		x[sa[i]]=cmp(y,sa[i-1],sa[i],j)? p-1:p++;

	}

}

void getheight(int *r,int n)

{

	int i,j,k=0;

	for(i=1;i<=n;i++)  rank[sa[i]]=i;

	for(i=0;i<n;i++)

	{

		if(k)

		k--;

		else

		k=0;

		j=sa[rank[i]-1];

		while(r[i+k]==r[j+k])

		k++;

		height[rank[i]]=k;

	}

}

void rmq_init(int n)

{

	for(int i=1;i<=n;i++)  dp[i][0]=height[i];

	for(int j=1;(1<<j)<=n;j++)

	for(int i=1;i+(1<<j)-1<=n;i++)

	dp[i][j]=dp[i][j-1]<dp[i+(1<<(j-1))][j-1]? dp[i][j-1]:dp[i+(1<<(j-1))][j-1];

} 

int rmq(int left,int right)

{

	int k=log2[right-left+1];

	//printf(":%d %d %d\n",k,left,right); 

	return min(dp[left][k],dp[right-(1<<k)+1][k]);

}

int main()

{

	int text,xxx=0;

	scanf("%d",&text);

	int num = 0, tot = 1;

    while(tot < maxn)

    {

        for(int i = tot; i < tot * 2 && i < maxn; ++i)

            log2[i] = num;

        num++; tot *= 2;

    }

	while(text--)

	{

		scanf("%s",str);

		int len=strlen(str),j=0;

		for(int i=0;i<len;i++)

		{

			s[j++]=str[i]-'a'+1;

		}

		s[j++]=29;

		for(int i=len-1;i>=0;i--)

		{

			s[j++]=str[i]-'a'+1;

		}

		s[j]=0;

		int len1=j;

		getsa(s,sa,len1+1,32);

		getheight(s,len1);

		rmq_init(len1);

		int sum=0;

		int cnt=0;

		for(int i=1;i<len1;i++)

		{

			cnt=cnt>height[i] ? height[i]:cnt;

			if(sa[i]<len)

			{

				int tmp=2*len-sa[i];

				int pp,qq;

				if(i<rank[tmp])

				pp=i;

				else

				pp=rank[tmp];

				if(i>rank[tmp])

				qq=i;

				else

				qq=rank[tmp];

				//int pp=min(i,rank[tmp]);

				int k=rmq(pp+1,qq);

				//printf("%d %d\n",i,rank[tmp]);

				//printf("%d %d %d\n",pp+1,qq,tmp);

				//printf("1:%d %d %d\n",i,rank[tmp],k);

				if(k>cnt)

				{

					sum+=k-cnt;

					cnt=k;

				}

			}

		}

		cnt=0;

		//printf("\n\n");

		for(int i=1;i<len1;i++)

		{

			cnt= (cnt>height[i]) ? height[i] : cnt;

			if(!sa[i])

			continue;

			if(sa[i]<len)

			{

				int tmp=2*len-sa[i]+1;

				int pp,qq;

				if(i<rank[tmp])

				pp=i;

				else

				pp=rank[tmp];

				if(i>rank[tmp])

				qq=i;

				else

				qq=rank[tmp];

				int k=rmq(pp+1,qq);

				printf("%d %d\n",pp+1,qq);

				//printf("%d %d\n",min(i,rank[tmp])+1,max(i,rank[tmp]));

				//printf("2:%d %d %d\n",i,rank[tmp],k);

				if(k>cnt)

				{

					sum+=k-cnt;

					cnt=k;

				}

			}

		}

		//printf("Case #%d: %d\n",++xxx,sum);

	}

	return 0;

}

 

你可能感兴趣的:(后缀数组)