SPOJ 题目705 New Distinct Substrings(后缀数组,求不同的子串个数)

SUBST1 - New 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 <= 50000

Output

For each test case output one number saying the number of distinct substrings.

Example

Input:
2
CCCCC
ABABA

Output:
5
9

ac代码

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#define min(a,b) (a>b?b:a)
#define max(a,b) (a>b?a:b)
using namespace std;
char str[50010];
int sa[50100],Rank[50100],rank2[50100],height[50010],c[50100],*x,*y,s[50100];
int n;
void cmp(int n,int sz)
{
	int i;
	memset(c,0,sizeof(c));
	for(i=0;i<n;i++)
		c[x[y[i]]]++;
	for(i=1;i<sz;i++)
		c[i]+=c[i-1];
	for(i=n-1;i>=0;i--)
		sa[--c[x[y[i]]]]=y[i];
}
void build_sa(int *s,int n,int sz)
{
	x=Rank,y=rank2;
	int i,j;
	for(i=0;i<n;i++)
		x[i]=s[i],y[i]=i;
	cmp(n,sz);
	int len;
	for(len=1;len<n;len<<=1)
	{
		int yid=0;
		for(i=n-len;i<n;i++)
		{
			y[yid++]=i;
		}
		for(i=0;i<n;i++)
			if(sa[i]>=len)
				y[yid++]=sa[i]-len;
			cmp(n,sz);
		swap(x,y);
		x[sa[0]]=yid=0;
		for(i=1;i<n;i++)
		{
			if(y[sa[i-1]]==y[sa[i]]&&sa[i-1]+len<n&&sa[i]+len<n&&y[sa[i-1]+len]==y[sa[i]+len])
				x[sa[i]]=yid;
			else
				x[sa[i]]=++yid;
		}
		sz=yid+1;
		if(sz>=n)
			break;
	}
	for(i=0;i<n;i++)
		Rank[i]=x[i];
}
void getHeight(int *s,int n)
{
	int k=0;
	for(int i=0;i<n;i++)
	{
		if(Rank[i]==0)
			continue;
		k=max(0,k-1);
		int j=sa[Rank[i]-1];
		while(s[i+k]==s[j+k])
			k++;
		height[Rank[i]]=k;
	}
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int i;
		scanf("%s",str);
		int len=strlen(str);
		for(i=0;i<len;i++)
			s[i]=str[i];
		s[len]=0;
		build_sa(s,len+1,260);
		getHeight(s,len);
		int sum=0;
		for(i=1;i<=len;i++)
		{
			sum+=len-sa[i]-height[i];
		}
		printf("%d\n",sum);
	}
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-28 18:44:39

SPOJ 题目705 New Distinct Substrings(后缀数组,求不同的子串个数)的相关文章

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

SPOJ694--- DISUBSTR - Distinct Substrings(后缀数组)

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 one number saying the number of distin

SPOJ 694 || 705 Distinct Substrings ( 后缀数组 &amp;&amp; 不同子串的个数 )

题意 : 对于给出的串,输出其不同长度的子串的种类数 分析 : 有一个事实就是每一个子串必定是某一个后缀的前缀,换句话说就是每一个后缀的的每一个前缀都代表着一个子串,那么如何在这么多子串or后缀的前缀中找出不同的并计数呢?思路就是所有的可能子串数 - 重复的子串数.首先我们容易得到一个长度为 len 的串的子串数为 len * ( len + 1) / 2.那如何知道重复的子串数呢?答案就是利用后缀数组去跑一遍 Height ,得到所有的最长公共前缀(LCP),这些最长公共前缀的值都存在了 He

spoj Distinct Substrings 后缀数组

给定一个字符串,求不相同的子串的个数. 假如给字符串“ABA";排列的子串可能: A B A AB  BA ABA 共3*(3+1)/2=6种; 后缀数组表示时: A ABA BA 对于A和AB height[i]=1; 表明一个长度公共,所以ABA中多出现了A这个子串,所以6-1=5: 对于ABA BA height[i]=0,所以不需要减去. 最后答案为5: #include<iostream> #include<stdio.h> #include<string

SPOJ694&amp;&amp;SPOJ705:Distinct Substrings(后缀数组)

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 one string, whose length is <= 1000 Output For each test case output one number saying the numb

HDOJ 题目4416 Good Article Good sentence(后缀数组求a串子串在b串中不出现的种类数)

-每周六晚的BestCoder(有米!) Good Article Good sentence Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2784    Accepted Submission(s): 785 Problem Description In middle school, teachers used to encour

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

[spoj694&amp;spoj705]New Distinct Substrings(后缀数组)

题意:求字符串中不同子串的个数. 解题关键:每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相同的前缀的个数. 1.总数减去height数组的和即可. 注意这里height中为什么不需要进行组合计数,因为,每一个height的左端点已经确定,所以只需变动右端点,总共$height[i]$种情况. 2.如果所有的后缀按照 suffix(sa[1]), suffix(sa[2]),suffix(sa[3]), …… ,suffix(sa[n])的顺序计算,不难发现,对于每一次新加进来

POJ 3415 Common Substrings(后缀数组求重复字串)

题目大意:给你两个字符串,让你求出来两个字符串之间的重复子串长度大于k的有多少个. 解题思路: 先说论文上给的解释:基本思路是计算A的所有后缀和B的所有后缀之间的最长公共前缀的长度,把最长公共前缀长度不小于k的部分全部加起来.先将两个字符串连起来,中间用一个没有出现过的字符隔开.按height值分组后,接下来的工作便是快速的统计每组中后缀之间的最长公共前缀之和.扫描一遍,每遇到一个B的后缀就统计与前面的A的后缀能产生多少个长度不小于k的公共子串,这里A的后缀需要用一个单调的栈来高效的维护.然后对