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. java中的线程安全

    在Java中,线程的安全实际上指的是内存的安全,这是由操作系统决定的. 目前主流的操作系统都是多任务的,即多个进程同时运行.为了保证安全,每个进程只能访问分配给自己的内存空间,而不能访问别的.分配给别 ...

  2. 可保图片不变形的object-fit

    Object-fit 我们有时候浏览一些网站的时候,偶尔会遇到这种情况:  明显它喵的形变了,尤其是这种这么业余的失误,还是出现在一个专门做图片的网站上. 产生这种现象的原因是:图片写了固定的宽高,这 ...

  3. 玩转VSCode-完整构建VSCode开发调试环境

    随着VSCode的不断完善和强大,是时候将部分开发迁移到VS Code中了. 目前使用VS2019开发.NET Core应用,一直有一个想法,在VS Code中复刻VS的开发环境,同时迁移到VS Co ...

  4. C++中对C的扩展学习新增内容———面向对象(继承)函数扩展性及虚函数机制

    1.c语言中的多态,动态绑定和静态绑定 void do_speak(void(*speak)()) { speak(); } void pig_speak() { cout << &quo ...

  5. SpringBoot 源码解析 (六)----- Spring Boot的核心能力 - 内置Servlet容器源码分析(Tomcat)

    Spring Boot默认使用Tomcat作为嵌入式的Servlet容器,只要引入了spring-boot-start-web依赖,则默认是用Tomcat作为Servlet容器: <depend ...

  6. Ubuntu 18 安装搜狗输入法

    Ubuntu 18 安装搜狗输入法: 1. 搜狗输入法官网下载对应的Linux输入法 2. 双击 刚刚下载好的 deb 文件 3. 点击 install(安装) 4. 在 settings(系统设置) ...

  7. 队列+BFS (附vector初试)

    优先队列的使用: include<queue>//关联头文件 struct node{ int x,y; friend bool operator < (node d1,node d ...

  8. 力扣(LeetCode)查找常用字符 个人题解

    给定仅有小写字母组成的字符串数组 A,返回列表中的每个字符串中都显示的全部字符(包括重复字符)组成的列表.例如,如果一个字符在每个字符串中出现 3 次,但不是 4 次,则需要在最终答案中包含该字符 3 ...

  9. Project Euler 63: Powerful digit counts

    五位数\(16807=7^5\)也是一个五次幂,同样的,九位数\(134217728=8^9\)也是一个九次幂.求有多少个\(n\)位正整数同时也是\(n\)次幂? 分析:设题目要求的幂的底为\(n\ ...

  10. CSS RESET —— 浏览器样式重置

    CSS Reset 1. CSS Reset为什么存在? 只要您的客户存在使用不同浏览器(ie,firefox,chrome等)的可能,那你就不得不从完美的理想状态回到现实,因为不同核心的浏览器对CS ...