New Distinct Substrings

题目大意

给定一个字符串,求本质不同的子串个数

题解

SA常见思想:每一个子串都是某个后缀的前缀

考虑每一个后缀的贡献,首先他拥有n - sa[i]个(我是用的模板中,sa[i]的大小是0....n-1)前缀,这些前缀有height[i]个跟sa[i-1]相同,要减去。剩下的部分不可能与sa[i-1]之前的想通了,不然sa[i]会排在sa[i-1]前面

还要注意本题的字符集是小写字母(鬼知道样例是什么东西)

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <cmath> void swap(int &a, int &b){int tmp = a;a = b, b = tmp;}
void swap(int* &a, int* &b){int *tmp = a;a = b;b = tmp;}
int max(int a, int b){return a > b ? a : b;}
int min(int a, int b){return a < b ? a : b;}
void read(int &x)
{
x = 0;char ch = getchar(), c = ch;
while(ch < '0' || ch > '9') c = ch, ch = getchar();
while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
if(c == '-') x = -x;
} const int INF = 0x3f3f3f3f;
const int MAXN = 50000 + 10; struct SuffixArray
{
int s[MAXN], sa[MAXN], rank[MAXN], height[MAXN];
int t[MAXN], t2[MAXN], c[MAXN];
int n;
void clear(){n = 0;memset(sa, 0, sizeof(sa));} void build_sa(int m)
{
++ n;
int i,*x=t,*y=t2;
for(i=0;i<m;++i) c[i]=0;
for(i=0;i<n;++i) x[i]=s[i];
for(i=0;i<n;++i) c[x[i]]++;
for(i=1;i<m;++i) c[i]+=c[i-1];
for(i=n-1;i>=0;--i) sa[--c[x[i]]]=i;
for(int k=1;k<=n;k<<=1)
{
int p=0;
for(i=n-k;i<n;++i) y[p++]=i;
for(i=0;i<n;++i) if(sa[i]>=k) y[p++]=sa[i]-k;
for(i=0;i<m;++i) c[i]=0;
for(i=0;i<n;++i) c[x[i]]++;
for(i=1;i<m;++i) c[i]+=c[i-1];
for(i=n-1;i>=0;--i) sa[--c[x[y[i]]]]=y[i];
swap(x,y);
p=1;x[sa[0]]=0;
for(i=1;i<n;++i)
x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?p-1:p++;
if(p>=n) break;
m=p;
}
-- n;
} void build_height()
{
int i,j,k=0;
for(i=1;i<=n;++i) rank[sa[i]]=i;
for(i=0;i<n;++i)
{
if(k) k--;
j=sa[rank[i]-1];
while(s[i+k]==s[j+k]) k++;
height[rank[i]]=k;
}
}
}A; int t, ans;
char tmp[MAXN]; int main()
{
read(t);
for(;t;-- t)
{
ans = 0;
scanf("%s", tmp);
A.s[0] = tmp[0] - 'a' + 1;
for(A.n = 1;tmp[A.n];++ A.n) A.s[A.n] = tmp[A.n] - 'a' + 1;
A.s[A.n] = 0;
A.build_sa(30);
A.build_height(); //调试信息
/*for(int i = 1;i <= A.n;++ i)
printf("sa[%d]:%s\n", i, tmp + A.sa[i]);
for(int i = 1;i <= A.n;++ i)
printf("height[%d]:%d\n", i, A.height[i]); */ for(int i = 1;i <= A.n;++ i)
ans += A.n - A.sa[i] - A.height[i];
printf("%d\n", ans);
}
return 0;
}

SPOJ694 New Distinct Substrings的更多相关文章

  1. spoj694 DISUBSTR - Distinct Substrings

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

  2. 【SPOJ694】Distinct Substrings (SA)

    求不相同子串个数    该问题等价于求所有后缀间不相同前缀的个数..也就是对于每个后缀suffix(sa[i]),将贡献出n-sa[i]+1个,但同时,要减去那些重复的,即为height[i],故答案 ...

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

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

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

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

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

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

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

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

  7. DISUBSTR - Distinct Substrings

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

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

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

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

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

随机推荐

  1. NX二次开发-UFUN拉伸函数UF_MODL_create_extruded2

    NX9+VS2012 //NX二次开发中常用拉伸函数为UF_MODL_create_extruded2,但是此函数不能拉伸片体, //想要拉伸片体用函数UF_MODL_create_extruded. ...

  2. Mac OS 快速查询技巧

    今天不知道按到什么快捷键弹出了这个搜索框,试了试很强大 后来查了才知道要双击键盘上的key (⌘)就会弹出,这个搜索很强大,要先安装QQ,QQ自带的 版权声明:本文为博主原创文章,未经博主允许不得转载 ...

  3. hdu多校第九场 1002 (hdu6681) Rikka with Cake 树状数组维护区间和/离散化

    题意: 在一块长方形蛋糕上切若干刀,每一刀都是从长方形某条边开始,垂直于这条边,但不切到对边,求把长方形切成了多少块. 题解: 块数=交点数+1 因为对于每个交点,唯一且不重复地对应着一块蛋糕. 就是 ...

  4. [转]C# JSON格式的字符串读取到类中

    将JSON格式的字符串读取到类中 本例中建立JSON格式的字符串json,将其内容读取到Person类中 运行本代码需要添加引用动态库Newtonsoft.Json 程序代码: using Syste ...

  5. jquery scrollTop() 方法

    原文地址:http://www.w3school.com.cn/jquery/css_scrolltop.asp 实例 设置 元素中滚动条的垂直偏移: $(".btn1").cli ...

  6. JavaScript网页特效5则

    动态字幕 代码:在需要处加入 < marquee onmouseover=this.stop() onmouseout=this.start()>欢迎访问JavaScript教程网 特点: ...

  7. selenium基础(滚动条操作)

    滚动条操作:当待操作的元素在页面可是区域外时,要将待操作的元素滚动到可视区域当中 步骤:1.先找要将要操作的元素element = driver.find_element_by_xxxx(" ...

  8. Apsara Clouder基础技能认证:阿里巴巴编码规范 考试备考题库

    考试网址: https://edu.aliyun.com/clouder/exam/intro/33 共50道题 限时90分钟 阿里云大学Apsara Clouder基础技能认证——阿里巴巴编码规范认 ...

  9. 解决VS2012新建MVC4等项目时,收到此模板加载程序集“NuGet.VisualStudio.Interop…”的错误

    1.错误如图所示: 2.不管是VS2012,还是2013如果开始没安装Nuget包都或报这个错,因为VS2012就已经全面切换到使用NuGet这个第三方开源工具来管理项目包和引用模块了,使用VS201 ...

  10. 同步图计算实现pageRank算法

    pageRank算法是Google对网页重要性的打分算法. 一个用户浏览一个网页时,有85%的可能性点击网页中的超链接,有15%的可能性转向任意的网页.pageRank算法就是模拟这种行为. Rv:定 ...