SPOJ DISUBSTR Distinct Substrings

后缀数组水题

先求所有的子串数,根据长度枚举,共(n+1)*n/2种

当height[i]>0时,说明height[i]这个前缀与其他子串相同,减去这height[i]个子串

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 1005
int r[N],sa[N],height[N],rank[N],wa[N],wb[N],wv[N],ws[N];
char s[N];
int n;
int cmp(int *r,int a,int b,int l) {//因为长<l的字符串排名已经确定下来了,所以相邻的两个字符串如果首尾相同,则这两个字符串对于长为l而言是相同的
	return r[a]==r[b]&&r[a+l]==r[b+l];
}
void da(char *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;m=p,j<<=1){//每一次循环完了之后,sa存的都是某一长度的字符串的字典序排名
		for(i=n-j,p=0;i<n;i++) y[p++]=i;//第二关键字都为0
		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(char *r,int *sa,int n) {
	int i,j,k=0;
	for(i=1;i<=n;i++) rank[sa[i]]=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=1;i<=n;i++) printf("height[%d]: %d\n",i,height[i]);
	return;
}
int main(){
	#ifndef ONLINE_JUDGE
	freopen("in.txt","r",stdin);
	#endif
	int T;
	scanf("%d",&T);
	while(T--){
		 scanf("%s",s);
		 n=strlen(s);
		 for(int i=0;i<n;i++){
		 	r[i]=s[i];
		 }
		 r[n]=0;
		 da(s,sa,n+1,129);
		 calheight(s,sa,n);
		 int ans=(n+1)*n/2;
		 for(int i=1;i<=n;i++) ans-=height[i];
		 printf("%d\n",ans);
	}
}
时间: 2024-10-17 07:08:44

SPOJ DISUBSTR Distinct Substrings的相关文章

SPOJ - DISUBSTR Distinct Substrings (不相同的子串的个数)

Distinct Substrings  Time Limit: 159MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Description Given a string, we need to find the total number of its distinct substrings. Input T- number of test cases. T<=20;Each test case consists of

【SPOJ】Distinct Substrings(后缀自动机)

[SPOJ]Distinct Substrings(后缀自动机) 题面 Vjudge 题意:求一个串的不同子串的数量 题解 对于这个串构建后缀自动机之后 我们知道每个串出现的次数就是\(right/endpos\)集合的大小 但是实际上我们没有任何必要减去不合法的数量 我们只需要累加每个节点表示的合法子串的数量即可 这个值等于\(longest-shortest+1=longest-parent.longest\) #include<iostream> #include<cstdio&g

SPOJ 694. Distinct Substrings,705. New Distinct Substrings(后缀数组)

题目大意:给定长度为N的字符串,求出其中不相同子串的个数. 解题思路:每一个字串一定是某个后缀的前缀,那么原问题就可以等价于求所有后缀之间的不相同的前缀的个数.如果所有的后缀按照suffix(sa[1]),suffix(sa[2])--suffix(sa[n])的顺序计算,我们会发现对于每个新加进来的后缀suffix(sa[k]),它将产生n-sa[k]+1个新的前缀.但是其中有leight[k]个是和前面的字符串的前缀是相同的.所以suffix(sa[k])加进来增加的不同的子串的个数为n-s

Spoj 694 Distinct Substrings

Given a string, we need to find the total number of its distinct substrings. 给你一个字符中,统计有多少个不同的子串InputT- number of test cases. T<=20;Each test case consists of one string, whose length is <= 1000OutputFor each test case output one number saying the n

SPOJ 705 Distinct Substrings(后缀数组)

[题目链接] http://www.spoj.com/problems/SUBST1/ [题目大意] 给出一个串,求出不相同的子串的个数. [题解] 对原串做一遍后缀数组,按照后缀的名次进行遍历, 每个后缀对答案的贡献为n-sa[i]+1-h[i], 因为排名相邻的后缀一定是公共前缀最长的, 那么就可以有效地通过LCP去除重复计算的子串. [代码] #include <cstdio> #include <cstring> #include <algorithm> usi

spoj 694 Distinct Substrings(后缀数组)

题目:求一个字符串中所有不同子串个数 后缀数组经典题,每一个子串一定是某个后缀的前缀,那么问题便等价于求所有后缀之间的不相同的前缀个数.我们按sa的顺序来考虑,当加入sa[k]的时候,sa[k]这个后缀的长度为n-sa[k]-1,那么便有n-sa[k]-1个前缀,但是由heigh数组可知sa[k]与sa[k-1]有height[k]个前缀是相同的,所以要除去. 注意的是这道题题意有点坑,一开始以为字母只能是大写的而且长度在1000之内,可发现根本不是这样!!!!!!!!最后改了m的值又把数组开到

后缀数组 SPOJ 694 Distinct Substrings

题目链接 题意:给定一个字符串,求不相同的子串的个数 分析:我们能知道后缀之间相同的前缀的长度,如果所有的后缀按照 suffix(sa[0]), suffix(sa[1]), suffix(sa[2]), …… ,suffix(sa[n])的顺序计算,不难发现,对于每一次新加进来的后缀 suffix(sa[k]),它将产生 n-sa[k]+1 个新的前缀.但是其中有 height[k]个是和前面的字符串的前缀是相同的.所以 suffix(sa[k])将“贡献” 出 n-sa[k]+1- heig

spoj 694 Distinct Substrings 后缀数组

题目链接 求一个字符串中不相同的子串的个数. 子串的总数是(n+1)*n/2, 减去height[i]就可以. #include <iostream> #include <vector> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <map> #include <set> #include

SPOJ Distinct Substrings(后缀数组求不同子串个数,好题)

DISUBSTR - Distinct Substrings no tags Given a string, we need to find the total number of its distinct substrings. Input T- number of test cases. T<=20; Each test case consists of one string, whose length is <= 1000 Output For each test case output