HDU 3518 Description Boring counting

n<1000,最后查询的时候可以用n^2算法,如果是10000就不行了

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
#define N 1005
char s[N];
int r[N];
int wa[N],wb[N],wv[N],ws[N],Rank[N],sa[N],height[N];
int cmp(int *r,int a,int b,int l){
	return r[a]==r[b]&&r[a+l]==r[b+l];
}
void da(int *r,int *sa,int n,int m){
	int i,j,p,*x=wa,*y=wb;
	for(i=0;i<m;i++) ws[i]=0;
	for(i=0;i<n;i++) ws[x[i]=r[i]]++;
	for(i=1;i<m;i++) ws[i]+=ws[i-1];
	for(i=n-1;i>=0;i--) sa[--ws[x[i]]]=i;
	for(j=1,p=1;p<n;j<<=1,m=p){
		for(i=n-j,p=0;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++) ws[i]=0;
		for(i=0;i<n;i++) ws[wv[i]]++;
		for(i=1;i<m;i++) ws[i]+=ws[i-1];
		for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i];
		swap(x,y);
		for(p=1,x[sa[0]]=0,i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;//更新第一关键字和第二关键字合并后的排序
	}
	return;
}
void calheight(int *r,int *sa,int n) {
    int i,j,k=0;
    for(i=1;i<=n;i++) Rank[sa[i]]=i;  

    for(i=0;i<n;height[Rank[i++]]=k)  {
    	for(k?k--:0,j=sa[Rank[i]-1];r[i+k]==r[j+k];k++);//这里记得加分号
    }
    //for(i=0;i<=n;i++) printf("%d:%d\n",sa[i],height[i]);
    return;
}
int main(){
	#ifndef ONLINE_JUDGE
	freopen("in.txt","r",stdin);
	#endif
	while(scanf("%s",s)) {
		if(s[0]=='#') break;
		int l=strlen(s);
		for(int i=0;i<l;i++) r[i]=s[i];
		r[l]=0;
		da(r,sa,l+1,128);
		calheight(r,sa,l);
		ll ans=0,mini,maxi;

		for(int len=1;len<=l;len++) {//子串长度
			mini=sa[0];maxi=sa[0];
			for(int i=1;i<=l;i++){
				//根据height分组的时候,用个while是很常见的用法
				while(height[i]>=len &&i<=l){//注意i>l的时候要跳出循环,不然会由于上一个数据引起错误
					if(sa[i]<mini) mini=sa[i];
					if(sa[i]>maxi) maxi=sa[i];
					i++;
				}
				if(maxi-mini>=len) ans++;
				mini=sa[i];
				maxi=sa[i];
			}
		}
		printf("%I64d\n",ans);
	}
	return 0;
}
时间: 2024-11-06 21:30:49

HDU 3518 Description Boring counting的相关文章

hdu 3518 Boring counting(后缀数组)

Boring counting                                                                       Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem Description 035 now faced a tough problem,his english teacher gives him

后缀数组 --- HDU 3518 Boring counting

Boring counting Problem's Link:   http://acm.hdu.edu.cn/showproblem.php?pid=3518 Mean: 给你一个字符串,让你求出有多少个子串(无重叠)至少出现了两次. analyse: 后缀数组中height数组的运用,一般这个数组用得很少. 总体思路:分组统计的思想:将相同前缀的后缀分在一个组,然后对于1到len/2的每一个固定长度进行统计ans. 首先我们先求一遍后缀数组,并把height数组求出来.height数组代表的

Boring counting HDU - 3518 (后缀数组)

Boring counting \[ Time Limit: 1000 ms \quad Memory Limit: 32768 kB \] 题意 给出一个字符串,求出其中出现两次及以上的子串个数,要求子串之间不可以重合. 思路 对字符串后缀数组,然后枚举子串长度 \(len\),若某一段连续的 \(sa[i]\) 的 \(lcp \geq len\),那么说明这一段内存在一个长度为 \(lcp\) 的子串,而我们只需要其中的前 \(len\) 部分,接下来只要找出这个子串出现的最左和最右位置,

HDOJ 3518 Boring counting

SAM基本操作 拓扑求每个节点的  最左出现left,最右出现right,出现了几次num ...... 对于每一个出现两次以上的节点,对其所对应的一串子串的长度范围 [fa->len+1,len] 和其最大间距 right-left比较 即可...... Boring counting Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s):

HDOJ 题目3518 Boring counting(后缀数组,求不重叠重复次数最少为2的子串种类数)

Boring counting Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 2253    Accepted Submission(s): 924 Problem Description 035 now faced a tough problem,his english teacher gives him a string,whic

hdu 3518 后缀数组

Boring counting Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 2906    Accepted Submission(s): 1201 Problem Description 035 now faced a tough problem,his english teacher gives him a string,whic

BNUOJ 7629 Boring counting

Boring counting Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: 351864-bit integer IO format: %I64d      Java class name: Main 035 now faced a tough problem,his english teacher gives him a string,which consis

13年山东省赛 Boring Counting(离线树状数组or主席树+二分or划分树+二分)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud 2224: Boring Counting Time Limit: 3 Sec  Memory Limit: 128 MB Description In this problem you are given a number sequence P consisting of N integer and Pi is the ith element in the sequence.

UPC 2224 Boring Counting (离线线段树,统计区间[l,r]之间大小在[A,B]中的数的个数)

题目链接:http://acm.upc.edu.cn/problem.php?id=2224 题意:给出n个数pi,和m个查询,每个查询给出l,r,a,b,让你求在区间l~r之间的pi的个数(A<=pi<=B,l<=i<=r). 参考链接:http://www.cnblogs.com/zj62/p/3558967.html #include <iostream> #include <cstdio> #include <cstring> #incl