计蒜客 焦作网络赛 String and Times(后缀数组)

题目:给一个字符串问重复出现的次数在[A,B] 区间的子串有多少种。

思路:后缀数组,对于一个height[i],求height[i-1]---height[i]区间有多少个h满足存在大于等于h的连续的最长长度>=A并且<=B的一个序列(h的数量比较少可以单个枚举。。),这里用rmq来实现。然后另外算一下A==1的情况,也就是只出现了一次的子串有多少个(比赛时就是这里写错了,唉,我tmd弱智啊)。

#include
#include
#include
#include
using namespace std;
const int maxn=200010;
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 da(int str[],int sa[],int ra[],int height[],int n,int m)
{
	n++;
	int p,*x=t1,*y=t2;
	for(int i=0;i=0;i--) sa[--c[x[i]]]=i;
	for(int j=1;j<=n;j<<=1)
	{
		p=0;
		for(int i=n-j;i=j)  y[p++]=sa[i]-j;
		for(int i=0;i=0;i--) sa[--c[x[y[i]]]]=y[i];
		swap(x,y);
		p=1;x[sa[0]]=0;
		for(int i=1;i=n) break;
		m=p;
	}
	int k=0;
	n--;
	for(int i=0;i<=n;i++) ra[sa[i]]=i;
	for(int i=0;in) return 0;
    int t=mm[b-a+1];
    b-=(1<=1)
        {
        	A=max(A,1);
        	while(i<=n)
	        {
	    		int j=i+A-1,k=i+B-1,tmp=height[i-1];
	    		for(int t=height[i-1]+1;t<=height[i];t++)
		    		if(j<=n&&askRMQ(i,j)>=t&&askRMQ(j+1,k+1)

 

 

你可能感兴趣的:(字符串,后缀数组)