spoj694:http://www.spoj.com/problems/DISUBSTR/

题意:给以一个串,求这个串的所有不同子串的个数。

题解:第一次接触后缀数组,这里可以转化成,求所有子串后缀的前缀的个数,然后减去重复计算的。这里怎么减去重复的呢,就是我们还有height[]数组,height[i]表示sa[i]与sa[i-1]最长公共前缀,只要统计的时候,把前缀减去就好。

 #include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=;
char str[maxn];
int wa[maxn],wb[maxn],wv[maxn],wn[maxn],a[maxn],sa[maxn];
int cmp(int* r,int a,int b,int l)
{
return r[a]==r[b]&&r[a+l]==r[b+l];
}
//n为字符串长度,m为字符的取值范围,r为字符串。后面的j为每次排序时子串的长度
void DA(int* r,int* sa,int n,int m)
{
int i,j,p,*x=wa,*y=wb,*t;
///对R中长度为1的子串进行基数排序
for(i=; i<m; i++)wn[i]=;
for(i=; i<n; i++)wn[x[i]=r[i]]++;
for(i=; i<m; i++)wn[i]+=wn[i-];
for(i=n-; i>=; i--)sa[--wn[x[i]]]=i;
for(j=,p=; p<n; j*=,m=p)
{
//利用了上一次基数排序的结果,对待排序的子串的第二关键字进行了一次高效地基数排序
for(p=,i=n-j; i<n; i++)y[p++]=i;
for(i=; i<n; i++)if(sa[i]>=j)y[p++]=sa[i]-j;
///基数排序
for(i=; i<n; i++)wv[i]=x[y[i]];
for(i=; i<m; i++)wn[i]=;
for(i=; i<n; i++)wn[wv[i]]++;
for(i=; i<m; i++)wn[i]+=wn[i-];
for(i=n-; i>=; i--)sa[--wn[wv[i]]]=y[i];
///当p=n的时候,说明所有串都已经排好序了
///在第一次排序以后,rank数组中的最大值小于p,所以让m=p
for(t=x,x=y,y=t,p=,x[sa[]]=,i=; i<n; i++)
x[sa[i]]=cmp(y,sa[i-],sa[i],j)?p-:p++;
}
return;
}
///后缀数组 计算height数组
/**
height数组的值应该是从height[1]开始的,而且height[1]应该是等于0的。
原因是,+因为我们在字符串后面添加了一个0号字符,所以它必然是最小的
一个后缀。而字符串中的其他字符都应该是大于0的(前面有提到,使用倍
增算法前需要确保这点),所以排名第二的字符串和0号字符的公共前缀
(即height[1])应当为0.在调用calheight函数时,要注意height数组的范
围应该是[1..n]。所以调用时应该是calheight(r,sa,n)
而不是calheight(r,sa,n+1)。*/
int rank[maxn],height[maxn];
void calheight(int* r,int* sa,int n)
{
int i,j,k=;
for(i=; i<=n; i++)rank[sa[i]]=i;
for(i=; i<n; height[rank[i++]]=k)
for(k?k--:,j=sa[rank[i]-]; r[i+k]==r[j+k]; k++);
return;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
char str[];
scanf("%s",str);
int n=strlen(str);
for(int i=;i<n;i++) a[i]=(int)str[i];
a[n]=;
DA(a,sa,n+,);
calheight(a,sa,n);
int sum=;
for(int i=;i<=n;i++)
sum+=n-sa[i]-height[i];
printf("%d\n",sum);
}
return ;
}

Distinct Substrings的更多相关文章

  1. 后缀数组---New Distinct Substrings

    Description Given a string, we need to find the total number of its distinct substrings. Input T- nu ...

  2. SPOJ 694. Distinct Substrings (后缀数组不相同的子串的个数)转

    694. Distinct Substrings Problem code: DISUBSTR   Given a string, we need to find the total number o ...

  3. 后缀数组:SPOJ SUBST1 - New Distinct Substrings

    Given a string, we need to find the total number of its distinct substrings. Input T- number of test ...

  4. DISUBSTR - Distinct Substrings

    DISUBSTR - Distinct Substrings no tags  Given a string, we need to find the total number of its dist ...

  5. 705. New Distinct Substrings spoj(后缀数组求所有不同子串)

    705. New Distinct Substrings Problem code: SUBST1 Given a string, we need to find the total number o ...

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

    [SPOJ]Distinct Substrings(后缀自动机) 题面 Vjudge 题意:求一个串的不同子串的数量 题解 对于这个串构建后缀自动机之后 我们知道每个串出现的次数就是\(right/e ...

  7. 【SPOJ】Distinct Substrings/New Distinct Substrings(后缀数组)

    [SPOJ]Distinct Substrings/New Distinct Substrings(后缀数组) 题面 Vjudge1 Vjudge2 题解 要求的是串的不同的子串个数 两道一模一样的题 ...

  8. Distinct Substrings(spoj694)(sam(后缀自动机)||sa(后缀数组))

    Given a string, we need to find the total number of its distinct substrings. Input \(T-\) number of ...

  9. SPOJ Distinct Substrings【后缀数组】

    Given a string, we need to find the total number of its distinct substrings. Input T- number of test ...

  10. SPOJ 694&&SPOJ705: Distinct Substrings

    DISUBSTR - Distinct Substrings 链接 题意: 询问有多少不同的子串. 思路: 后缀数组或者SAM. 首先求出后缀数组,然后从对于一个后缀,它有n-sa[i]-1个前缀,其 ...

随机推荐

  1. [转] Tomcat 配置 SSL

    PS: keystore有自己的访问密码,这个保护层次要低一些,然后keystore里面存有自己的私钥,所以用户要破解的话,既要有keystore,又要有keystore的密码,p12是客户端keys ...

  2. 三分钟学会缓存工具DiskLruCache

    DiskLruCache是一个十分好用的android缓存工具,我们可以从GitHub上下载其源码:https://github.com/JakeWharton/DiskLruCache DiskLr ...

  3. 【Android】数据存储-java IO流文件存储

    1.数据持久化:将在内存中的瞬时数据保存在存储设备中.瞬时数据:设备关机数据丢失.持久化技术提供一种机制可以让数据在瞬时状态和持久状态之间转换. 2.Android中简单的三种存储方式:文件存储.Sh ...

  4. 使用httpModule做权限系统

    页面请求过程: 根据这个流程,网上一般的权限验证在:Http.Module.AuthorizeRequestHttp.Module.PreRequestHandlerExecute 例如使用前者: u ...

  5. [Unity官方文档翻译]ScrollRect

    官方地址:http://docs.unity3d.com/Manual/script-ScrollRect.html 一边学习一边翻译不知效率如何= = Scroll Rect 在小区域里展示大量内容 ...

  6. xml--小结④DTD的验证问题,不要用IE检验,IE不靠谱

    可以自己写代码 <script type="text/javascript"> var xmldoc = new ActiveXObject("Microso ...

  7. Oracle: Oracle行转列、列转行的Sql语句总结

    例子原型: ' ; 运行结果如下: 一.多字段的拼接 将两个或者多个字段拼接成一个字段: ' ; 运行结果: 二.行转列 将某个字段的多行结果,拼接成一个字段,获取拼接的字符串[默认逗号隔开] ' ; ...

  8. 7-1 DBA顾问培训内容@20141230

    1, 逻辑读还是物理读? 查询语句的实际执行计划. F5 预计执行计划. --如何产生实际执行计划 ??. --Session收集指令.   workload repository report fo ...

  9. js 判断一个点是否在一个多边形之内

    出处: https://github.com/substack/point-in-polygon/blob/master/index.js github: https://github.com/sub ...

  10. Java之加密(信息摘要)工具类(依赖:java.security.MessageDigest或org.apache.commons.codec.digest.DigestUtils)

    依赖于java.security.MessageDigest,支持MD5,SHA-1,SHA-256 import java.security.MessageDigest; import java.s ...