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.

题解:

本题题意就是给你一个字符串,让你找它有多少不同的子串;

其实就是SAM的板题,只要求每一个状态点的longest[i]-longest[fa[i]]的和就行了。

但由于是后缀数组专题,还是用后缀数组写:

参考代码:

后缀自动机:

#include<bits/stdc++.h>
using namespace std;
#define PI acos(-1.0)
#define mkp make_pair
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=1e5+;
char s[maxn];
struct SAM{
ll ans;
int fa[maxn<<],l[maxn<<],nxt[maxn<<][],last,cnt;
void Init()
{
memset(nxt[],,sizeof(nxt[]));
last=cnt=; ans=;
fa[]=;l[]=;
} int NewNode()
{
++cnt;
memset(nxt[cnt],,sizeof(nxt[cnt]));
fa[cnt]=l[cnt]=;
return cnt;
} void Add(int c)
{
int p=last,np=NewNode();
last=np;l[np]=l[p]+;
while(p&&!nxt[p][c]) nxt[p][c]=np,p=fa[p];
if(!p) fa[np]=;
else
{
int q=nxt[p][c];
if(l[q]==l[p]+) fa[np]=q;
else
{
int nq=NewNode();
memcpy(nxt[nq],nxt[q],sizeof(nxt[q]));
fa[nq]=fa[q];
l[nq]=l[p]+;
fa[q]=fa[np]=nq;
while(nxt[p][c]==q) nxt[p][c]=nq,p=fa[p];
}
}
ans+=(l[last]-l[fa[last]])*1ll;
} void Query()
{
Init();
for(int i=,len=strlen(s);i<len;++i) Add(s[i]-'A');
printf("%lld\n",ans);
}
} sam; int main()
{
int N;
scanf("%d",&N);
while(N--)
{
sam.Init();
scanf("%s",s);
sam.Query();
}
return ;
}

后缀数组:

#include<iostream>
#include<cstdio>
#include<cstring>
#define rint register int
#define ini inline int
#define maxn 1000050
using namespace std;
char str[maxn];
int y[maxn<<],x[maxn<<],c[maxn];
int sa[maxn],rk[maxn],height[maxn];
int n,m,s[maxn]; inline void get_SA()
{
for(int i=;i<=m;++i) c[i]=;
for(int i=;i<=n;++i) ++c[x[i]=s[i]];
for(int i=;i<=m;++i) c[i]+=c[i-];
for(int i=n;i>=;--i) sa[c[x[i]]--]=i;
for(int k=;k<=n;k<<=)
{
int num=;
for(int i=n-k+;i<=n;++i) y[++num]=i;
for(int i=;i<=n;++i) if(sa[i]>k) y[++num]=sa[i]-k;
for(int i=;i<=m;++i) c[i]=;
for(int i=;i<=n;++i) ++c[x[i]];
for(int i=;i<=m;++i) c[i]+=c[i-];
for(int i=n;i>=;--i) sa[c[x[y[i]]]--]=y[i],y[i]=;
swap(x,y);
x[sa[]]=;
num=;
for(rint i=;i<=n;++i)
x[sa[i]]=(y[sa[i]]==y[sa[i-]]&&y[sa[i]+k]==y[sa[i-]+k])?num:++num;
if(num==n) break;
m=num;
}
}
inline void get_height()
{
int k=;
for(int i=;i<=n;++i) rk[sa[i]]=i;
for(int i=;i<=n;++i)
{
if(rk[i]==) continue;//第一名height为0
if(k) --k;//h[i]>=h[i-1]-1;
rint j=sa[rk[i]-];
while(j+k<=n&&i+k<=n&&s[i+k]==s[j+k]) ++k;
height[rk[i]]=k;//h[i]=height[rk[i]];
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",str+);
n=strlen(str+);m=;
for(int i=;i<=n;++i) s[i]=str[i]-'A'+;
get_SA();
get_height();
//for(int i=1;i<=n;++i) cout<<sa[i]<<" "<<height[i]<<endl;
int ans=;
for(int i=;i<=n;++i) ans+=n-sa[i]+-height[i];
printf("%d\n",ans);
}
return ;
}

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

  1. 字符串的模板 Manacher kmp ac自动机 后缀数组 后缀自动机

    为何scanf("%s", str)不需要&运算 经常忘掉的字符串知识点,最好不加&,不加&最标准,指针如果像scanf里一样加&是错的,大概是未定 ...

  2. 【整理】如何选取后缀数组&&后缀自动机

    后缀家族已知成员         后缀树         后缀数组         后缀自动机         后缀仙人掌         后缀预言         后缀Splay ? 后缀树是后缀数 ...

  3. loj6173 Samjia和矩阵(后缀数组/后缀自动机)

    题目: https://loj.ac/problem/6173 分析: 考虑枚举宽度w,然后把宽度压位集中,将它们哈希 (这是w=2的时候) 然后可以写一下string=“ac#bc” 然后就是求这个 ...

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

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

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

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

  6. spoj - Distinct Substrings(后缀数组)

    Distinct Substrings 题意 求一个字符串有多少个不同的子串. 分析 又一次体现了后缀数组的强大. 因为对于任意子串,一定是这个字符串的某个后缀的前缀. 我们直接去遍历排好序后的后缀字 ...

  7. SPOJ Distinct Substrings【后缀数组】

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

  8. spoj Distinct Substrings 后缀数组

    给定一个字符串,求不相同的子串的个数. 假如给字符串“ABA";排列的子串可能: A B A AB  BA ABA 共3*(3+1)/2=6种; 后缀数组表示时: A ABA BA 对于A和 ...

  9. SPOJ694 DISUBSTR --- 后缀数组 / 后缀自动机

    SPOJ694 DISUBSTR 题目描述: Given a string, we need to find the total number of its distinct substrings. ...

随机推荐

  1. jdk8 函数式编程概念

    yls 2019/11/7 函数式接口 如果一个接口只有一个抽象方法,那么该接口就是函数式接口 如果我们在某接口上声明了FunctionalInterface注解,那么编译器就会按照函数式接口的定义来 ...

  2. (线段树)A Corrupt Mayor's Performance Art

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5023 题意: 区间更新, 区间询问: 题解: 区间更新, 区间询问, 一共30种颜色, 可用int 来 ...

  3. mongodb存储二进制数据

    mongodb 3.x存储二进制数据并不是以base64的方式,虽然在mongo客户端的查询结果以base64方式显示,请放心使用.下面来分析存储文件的存储内容.base64编码数据会增长1/3成为顾 ...

  4. 解构ffmpeg(一)

    ffmpeg应用程序项目将其核心库libav*的使用或编程抽象成FilterGraph,InputFile,OutputFile,InputStream,OutputStream,InputFilte ...

  5. 【论文阅读】The Contextual Loss for Image Transformationwith Non-Aligned Data(ECCV2018 oral)

    目录: 相关链接 方法亮点 相关工作 方法细节 实验结果 总结与收获 相关链接 论文:https://arxiv.org/abs/1803.02077 代码:https://github.com/ro ...

  6. 原生JS scroll()、scrollTo()、scrollBy()

    scroll()  此方法接收两个参数,依次为X坐标和Y坐标:设置滚动条的偏移位置 scrollTo() 此方法和scroll()作用一样,都是设置滚动条的偏移位置. scrollBy() 此法发同样 ...

  7. 2019-11-24:postgresql数据库安装,最后报错failed to load SQLModule 问题的解决方案

    安装环境:Windows 10 问题描述:Failed to load sql modules into the database cluster 原因在于 Postgresql 没有安装完全. 解决 ...

  8. 2019-10-10:渗透测试,基础学习,mysql语法基础,笔记

    mysql常用命令mysql -u用户名 -p,登录方式也称为,二进制方式exit 退出mysql 查看mysql版本select version(); 查看mysql所有数据库show dateba ...

  9. Gemini.Workflow 双子工作流高级教程:数据库设计及各表作用说明

    整体数据库设计,可见这一篇:Gemini.Workflow 双子工作流高级教程:数据库-设计文档 这里对各数据表进行介绍: 工作流里的设计表并不多,核心只有以下8个: 下面按照流程的顺序来介绍一下表的 ...

  10. requests请求库

    # coding = utf-8 """ 同urllib一样 requests 也是发送http请求的第三方库 兼容Python2和3 实现了http的绝大部分功能. 安 ...