SPOJ- Distinct Substrings(后缀数组&后缀自动机)
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(后缀数组&后缀自动机)的更多相关文章
- 字符串的模板 Manacher kmp ac自动机 后缀数组 后缀自动机
为何scanf("%s", str)不需要&运算 经常忘掉的字符串知识点,最好不加&,不加&最标准,指针如果像scanf里一样加&是错的,大概是未定 ...
- 【整理】如何选取后缀数组&&后缀自动机
后缀家族已知成员 后缀树 后缀数组 后缀自动机 后缀仙人掌 后缀预言 后缀Splay ? 后缀树是后缀数 ...
- loj6173 Samjia和矩阵(后缀数组/后缀自动机)
题目: https://loj.ac/problem/6173 分析: 考虑枚举宽度w,然后把宽度压位集中,将它们哈希 (这是w=2的时候) 然后可以写一下string=“ac#bc” 然后就是求这个 ...
- Distinct Substrings(spoj694)(sam(后缀自动机)||sa(后缀数组))
Given a string, we need to find the total number of its distinct substrings. Input \(T-\) number of ...
- SPOJ Distinct Substrings(后缀数组求不同子串个数,好题)
DISUBSTR - Distinct Substrings no tags Given a string, we need to find the total number of its dist ...
- spoj - Distinct Substrings(后缀数组)
Distinct Substrings 题意 求一个字符串有多少个不同的子串. 分析 又一次体现了后缀数组的强大. 因为对于任意子串,一定是这个字符串的某个后缀的前缀. 我们直接去遍历排好序后的后缀字 ...
- SPOJ Distinct Substrings【后缀数组】
Given a string, we need to find the total number of its distinct substrings. Input T- number of test ...
- spoj Distinct Substrings 后缀数组
给定一个字符串,求不相同的子串的个数. 假如给字符串“ABA";排列的子串可能: A B A AB BA ABA 共3*(3+1)/2=6种; 后缀数组表示时: A ABA BA 对于A和 ...
- SPOJ694 DISUBSTR --- 后缀数组 / 后缀自动机
SPOJ694 DISUBSTR 题目描述: Given a string, we need to find the total number of its distinct substrings. ...
随机推荐
- 用这个库 3 分钟实现让你满意的表格功能:Bootstrap-Table
本文作者:HelloGitHub-kalifun 这是 HelloGitHub 推出的<讲解开源项目>系列,今天给大家推荐一个基于 Bootstrap 和 jQuery 的表格插件:Boo ...
- mysql中int、bigint、smallint、tinyint 长度
mysql中int.bigint.smallint.tinyint 长度 bigint -2^63 (-9223372036854775808) 到 2^63-1 (92233720368547758 ...
- Test Complete 的自动化测试 --- 三角形
Test Complete 的自动化测试 --- 三角形 PS:工具:Test Complete , OS:win 10 这里做三角形的测试与上一篇博客做计算器的测试大致一样,都是对.exe的执行文件 ...
- nyoj 811-变态最大值 (max)
811-变态最大值 内存限制:64MB 时间限制:1000ms 特判: No 通过数:6 提交数:15 难度:1 题目描述: Yougth讲课的时候考察了一下求三个数最大值这个问题,没想到大家掌握的这 ...
- IBM-X3850-4U诊断面板信息
IBM X3850 4U 指示灯 描述 OVERSPEC 没有足够的电量为系统供电.NONRED和LOG指示灯可能也点亮 PS 一个电源故障或者被电源未插 LINK 保留 CPU CPU出现故障.丢失 ...
- shodan 文档学习笔记
Table of Contents 1. Introduction 1.1. All About the Data 1.2. Data Collection 1.3. SSL in Depth 1.3 ...
- 使用 Topshelf 组件一步一步创建 Windows 服务 (2) 使用Quartz.net 调度
上一篇说了如何使用 Topshelf 组件快速创建Windows服务,接下来介绍如何使用 Quartz.net 关于Quartz.net的好处,网上搜索都是一大把一大把的,我就不再多介绍. 先介绍需要 ...
- no matches for kind "Deployment" in version "extensions/v1beta1"
0x00 Problem [root@k8sm90 demo]# kubectl create -f tomcat-deployment.yaml error: unable to recognize ...
- 我的第一个python web 开发框架
1:数据库结构设计与创建 小白做好前端html设计后,马上开始进入数据库结构设计步骤. 在开始之前,小白回忆了一下老大在公司里培训时讲过的数据库设计解说: 对于初学者来说,很多拿到原型时不知道怎么设计 ...
- 灵魂拷问:为什么 Java 字符串是不可变的?
在逛 programcreek 的时候,发现了一些精妙绝伦的主题.比如说:为什么 Java 字符串是不可变的?像这类灵魂拷问的主题,非常值得深思. 对于绝大多数的初级程序员来说,往往停留在" ...