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 distinct substrings.

Example

Sample Input:
2
CCCCC
ABABA

Sample Output:
5
9

Explanation for the testcase with string ABABA: 
len=1 : A,B
len=2 : AB,BA
len=3 : ABA,BAB
len=4 : ABAB,BABA
len=5 : ABABA
Thus, total number of distinct substrings is 9.

题意:

求出大写的字符串里不同的子串。默写了一遍后缀自动机。今天主要是练习后缀数组。

注意:

  • 注意是大写还是小写;
  • 注意init初始化的时候没有一次性memset,所以下面要把每个新出现的点memset。不要搞忘。

后缀自动机:

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=;
struct SAM
{
int ch[maxn][],fa[maxn],maxlen[maxn],Last,sz;
void init()
{
sz=Last=; fa[]=maxlen[]=;
memset(ch[],,sizeof(ch[]));
}
void add(int x)
{
int np=++sz,p=Last;Last=np;
memset(ch[np],,sizeof(ch[np]));
maxlen[np]=maxlen[p]+;
while(p&&!ch[p][x]) ch[p][x]=np,p=fa[p];
if(!p) fa[np]=;
else {
int q=ch[p][x];
if(maxlen[p]+==maxlen[q]) fa[np]=q;
else {
int nq=++sz;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
maxlen[nq]=maxlen[p]+;
fa[nq]=fa[q];
fa[q]=fa[np]=nq;
while(p&&ch[p][x]==q) ch[p][x]=nq,p=fa[p];
}
}
}
};
SAM Sam;
int main()
{
char chr[maxn];
int T,ans,i,L;
scanf("%d",&T);
while(T--){
Sam.init();ans=;
scanf("%s",chr);
L=strlen(chr);
for(i=;i<L;i++) Sam.add(chr[i]-'A');
for(i=;i<=Sam.sz;i++) ans+=Sam.maxlen[i]-Sam.maxlen[Sam.fa[i]];
printf("%d\n",ans);
}
return ;
}

后缀数组:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=;
char ch[maxn];
int L;
struct SA
{
int cntA[maxn],cntB[maxn],A[maxn],B[maxn];
int rank[maxn],sa[maxn],tsa[maxn],ht[maxn];void sort()
{
for (int i = ; i < ; i ++) cntA[i] = ;
for (int i = ; i <= L; i ++) cntA[ch[i]] ++;
for (int i = ; i < ; i ++) cntA[i] += cntA[i - ];
for (int i = L; i; i --) sa[cntA[ch[i]] --] = i;
rank[sa[]] = ;
for (int i = ; i <= L; i ++){
rank[sa[i]] = rank[sa[i - ]];
if (ch[sa[i]] != ch[sa[i - ]]) rank[sa[i]] ++;
}
for (int l = ; rank[sa[L]] < L; l <<= ){
for (int i = ; i <= L; i ++) cntA[i] = ;
for (int i = ; i <= L; i ++) cntB[i] = ;
for ( int i = ; i <= L; i ++){
cntA[A[i] = rank[i]] ++;
cntB[B[i] = (i + l <= L) ? rank[i + l] : ] ++;
}
for (int i = ; i <= L; i ++) cntB[i] += cntB[i - ];
for (int i = L; i; i --) tsa[cntB[B[i]] --] = i;
for (int i = ; i <= L; i ++) cntA[i] += cntA[i - ];
for (int i = L; i; i --) sa[cntA[A[tsa[i]]] --] = tsa[i];
rank[sa[]] = ;
for (int i = ; i <= L; i ++){
rank[sa[i]] = rank[sa[i - ]];
if (A[sa[i]] != A[sa[i - ]] || B[sa[i]] != B[sa[i - ]]) rank[sa[i]] ++;
}
}
}
void getheight()
{
for (int i = , j = ; i <= L; i ++){
if (j) j --;
while (ch[i + j] == ch[sa[rank[i] - ] + j]) j ++;
ht[rank[i]] = j;
}
}
};
SA Sa;
int main()
{
int T,ans,i;
scanf("%d",&T);
while(T--){
ans=;
scanf("%s",ch+);
L=strlen(ch+);
Sa.sort();
Sa.getheight();
for(i=;i<=L;i++) ans+=L-Sa.sa[i]+-Sa.ht[i];
printf("%d\n",ans);
}
return ;
}

SPOJ705 Distinct Substrings (后缀自动机&后缀数组)的更多相关文章

  1. poj 1743 Musical Theme 后缀自动机/后缀数组/后缀树

    题目大意 直接用了hzwer的题意 题意:有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复的主题."主题&qu ...

  2. [模板] 后缀自动机&&后缀树

    后缀自动机 后缀自动机是一种确定性有限状态自动机, 它可以接收字符串\(s\)的所有后缀. 构造, 性质 翻译自毛子俄罗斯神仙的博客, 讲的很好 后缀自动机详解 - DZYO的博客 - CSDN博客 ...

  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. Spoj-DISUBSTR - Distinct Substrings~New Distinct Substrings SPOJ - SUBST1~(后缀数组求解子串个数)

    Spoj-DISUBSTR - Distinct Substrings New Distinct Substrings SPOJ - SUBST1 我是根据kuangbin的后缀数组专题来的 这两题题 ...

  5. Distinct Substrings SPOJ - DISUBSTR 后缀数组

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

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

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

  7. SPOJ SUBLEX - Lexicographical Substring Search 后缀自动机 / 后缀数组

    SUBLEX - Lexicographical Substring Search Little Daniel loves to play with strings! He always finds ...

  8. 回文树&后缀自动机&后缀数组

    KMP,扩展KMP和Manacher就不写了,感觉没多大意思.   之前感觉后缀自动机简直可以解决一切,所以不怎么写后缀数组.   马拉车主要是通过对称中心解决问题,有的时候要通过回文串的边界解决问题 ...

  9. POJ3080 POJ3450Corporate Identity(广义后缀自动机||后缀数组||KMP)

    Beside other services, ACM helps companies to clearly state their “corporate identity”, which includ ...

随机推荐

  1. 中国程序员如何去 Facebook 工作?

    1.在Facebook,可以选择哪里工作? Facebook 在内地确实没有 Office ,但可以在https://www.facebook.com/careers/?ref=pf#location ...

  2. 快捷标签和ajax、json返回数据

    <if 判断条件>标签</if><import>标签可以链接外部的样式表,和js<import file="js.util.Array" ...

  3. 海康,睿网设备SDK调试

    引入 外部dll  DllImport [DllImport(@"../bin/HCNetSDK.dll")] 问题1: 找不到模块.... 解决:  [DllImport(@&q ...

  4. sgu 1348 Goat in the Garden 2【点到线段的距离】

    链接: http://acm.timus.ru/problem.aspx?space=1&num=1348 http://acm.hust.edu.cn/vjudge/contest/view ...

  5. iptables的用例

    iptables书写思路顺序 1.协议 icmp 2.哪个功能和目标:过滤,拒绝 3.数据包流向:外到内 4.哪个链适合:越早越好,INPUT 5.源地址和目标地址 练习1.禁止某些主机或网络访问本机 ...

  6. Linux中rpm包管理器

    包全名: 1.操作的包是没有安装的软件包时,使用全名,而且要注意路径 2.例如:jdk-8u131-linux-x64.rpm包名: 1.操作的是已经安装好的软件包,使用包名,是搜索/var/lib/ ...

  7. bug-4——bootStrap中的table语言设置

    $(document).ready(function() {     $('.datatable').dataTable( {                 "Language" ...

  8. CentOS 7 巨大变动之 systemd 取代 SysV的Init

    1 systemd是什么 首先systmed是一个用户空间的程序,属于应用程序,不属于Linux内核范畴,Linux内核的主要特征在所有发行版中是统一的,厂商可以自由改变的是用户空间的应用程序.   ...

  9. Bootstrap学习2--组件-列表组

    备注:最新Bootstrap手册:http://www.jqhtml.com/bootstraps-syntaxhigh/index.html 1.列表组 列表组是Bootstrap框架新增的一个组件 ...

  10. sql查询字段是否为空

    sql 查询某字段为空 select * from 表名 where 字段名 is null sql 查询某字段不为空 select * from 表名 where 字段名 is not null s ...