hdu 3518 后缀数组

晚饭前写的代码,一直wa,一直想不通,后来写程序对拍了,一百组数据中错了一组,然后还是想不通为什么的,然后的然后看了别人的代码,然后瞬间知道自己为什么wa!还是对后缀数组了解的不够,自己默认的是sa中排在前面的然后在字符串数组中下标也是在前面的,然后就没有挨个比较相同长度中的取最大值和最小值,所以wa的可怜啊,不过在比赛前又找到自己的一个缺陷好高兴啊,说明以后做这类题ac率又提高了,哈哈!

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<climits>
#include<map>
using namespace std;

#define rep(i,n) for(int i=0; i<n; i++)
#define repf(i,n,m) for(int i=(n); i<=(m); ++i)
#define repd(i,n,m) for(int i=(n); i>=(m); --i) 
#define ll long long
#define arc(a) ((a)*(a))
#define inf 100000
#define exp 0.000001
#define N 3005
char s[N];
int n;
int sa[N*2],high[N*2],rank[N*2],tmp[N*2],top[N*2];
void makesa()
{
	memset(sa,0,sizeof(sa));
	memset(high,0,sizeof(high));
	memset(rank,0,sizeof(rank));
	memset(tmp,0,sizeof(tmp));
	memset(top,0,sizeof(top));
	n=strlen(s);
	n++;
	s[n]='$';
	int na,len;
	na=(n<256?256:n);
	memset(top,0,sizeof(top));
	rep(i,n) top[rank[i]=s[i] & 0xff]++;
	repf(i,1,na-1) top[i]+=top[i-1];
	rep(i,n) sa[--top[rank[i]]]=i;
	for(len=1; len<n; len<<=1){
		int j;
		rep(i,n){
			j=sa[i]-len;
			if(j<0) j+=n;
			tmp[top[rank[j]]++]=j;
		}
		sa[tmp[top[0]=0]]=j=0;
		repf(i,1,n-1)
		{
			if(rank[tmp[i]]!=rank[tmp[i-1]] || rank[tmp[i]+len]!=rank[tmp[i-1]+len])
				top[++j]=i;
			sa[tmp[i]]=j;
		}
		rep(j,n+1) rank[j]=sa[j];
		rep(j,n+1) sa[j]=tmp[j];
		if(j>=n-1) break;
	}
}
void lcp()
{
	int i,j,k;
	high[0]=0;
	j=rank[0];
	for(i=0,k=0; i<n-1; i++,k++)
	 while(k>=0 && s[i]!=s[sa[j-1]+k])
		 high[j]=(k--),j=rank[sa[j]+1];
}

void solve()
{
	int ans=0;
	int l,r;
	repf(i,1,n/2)
	{
		l=1200,r=-1;
		repf(j,1,n-1)
		{
			if(high[j]>=i)
			{
				r=max(r,sa[j]);
				r=max(r,sa[j-1]);
				l=min(l,min(sa[j],sa[j-1]));
			}
			else
			{
				if(r-l>=i) ans++;
				l=1200,r=-1;
			}
		}
		if(l!=1200 && r!=-1) if(r-l>=i) ans++;
	}
	cout<<ans<<endl;
}
int main()
{ 
   while(scanf("%s",s))
   {
	   int len=strlen(s);
	   if(len==1 && s[0]=='#') break;
	   makesa();
	   lcp();
	   solve();
   }
   return 0;
}
  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

淡定的小Y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值