spoj New Distinct Substrings
vjudge原地爆炸...
题意:求一个字符串不同的子串的个数
策略:后缀数组
利用后缀数组的sa和height两个功能强大的数组,我们可以实现上述操作
首先有个很显然的结论:一个字符串的所有子串=它后缀的所有前缀
这是很显然的,因为一个后缀的前缀遍历了所有以该后缀起点为起点的字符串的子串,那么如果我们遍历所有后缀的,就能找出这个字符串的所有子串了
所以对于一个起点为sa[i]的字符串,最多能提供的贡献就是l-sa[i]+1,而再考虑重复字符串的个数,也就是这个后缀所有的与其他后缀最长的公共前缀,这个后缀的贡献就是l-sa[i]+1-height[i]
然后累计即可
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
int sa[50005];
int rk[50005];
int height[50005];
int f1[50005];
int f2[50005];
int f3[50005];
int has[50005];
char s[50005];
int l,m=127;
void init()
{
memset(sa,0,sizeof(sa));
memset(rk,0,sizeof(rk));
memset(has,0,sizeof(has));
memset(f1,0,sizeof(f1));
memset(f2,0,sizeof(f2));
memset(f3,0,sizeof(f3));
memset(height,0,sizeof(height));
m=127;
}
void turnit()
{
memcpy(f3,f1,sizeof(f3));
memcpy(f1,f2,sizeof(f1));
memcpy(f2,f3,sizeof(f2));
}
void get_sa()
{
for(int i=1;i<=l;i++)
{
f1[i]=s[i];
has[f1[i]]++;
}
for(int i=2;i<=m;i++)
{
has[i]+=has[i-1];
}
for(int i=l;i>=1;i--)
{
sa[has[f1[i]]--]=i;
}
for(int k=1;k<=l;k<<=1)
{
int tot=0;
for(int i=l-k+1;i<=l;i++)
{
f2[++tot]=i;
}
for(int i=1;i<=l;i++)
{
if(sa[i]>k)
{
f2[++tot]=sa[i]-k;
}
}
for(int i=1;i<=m;i++)
{
has[i]=0;
}
for(int i=1;i<=l;i++)
{
has[f1[i]]++;
}
for(int i=2;i<=m;i++)
{
has[i]+=has[i-1];
}
for(int i=l;i>=1;i--)
{
sa[has[f1[f2[i]]]--]=f2[i];
f2[i]=0;
}
turnit();
f1[sa[1]]=1;
tot=1;
for(int i=2;i<=l;i++)
{
if(f2[sa[i]]==f2[sa[i-1]]&&f2[sa[i]+k]==f2[sa[i-1]+k])
{
f1[sa[i]]=tot;
}else
{
f1[sa[i]]=++tot;
}
}
if(tot==l)
{
break;
}
m=tot;
}
for(int i=1;i<=l;i++)
{
rk[sa[i]]=i;
}
int f=0;
for(int i=1;i<=l;i++)
{
if(rk[i]==1)
{
continue;
}
if(f)
{
f--;
}
int j=sa[rk[i]-1];
while(s[i+f]==s[j+f])
{
f++;
}
height[rk[i]]=f;
}
}
void solve()
{
int ss=0;
for(int i=1;i<=l;i++)
{
ss-=l-sa[i]+1-height[i];
}
printf("%d\n",ss);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
init();
scanf("%s",s+1);
l=strlen(s+1);
get_sa();
solve();
}
return 0;
}
spoj New Distinct Substrings的更多相关文章
- 【SPOJ】Distinct Substrings(后缀自动机)
[SPOJ]Distinct Substrings(后缀自动机) 题面 Vjudge 题意:求一个串的不同子串的数量 题解 对于这个串构建后缀自动机之后 我们知道每个串出现的次数就是\(right/e ...
- 【SPOJ】Distinct Substrings/New Distinct Substrings(后缀数组)
[SPOJ]Distinct Substrings/New Distinct Substrings(后缀数组) 题面 Vjudge1 Vjudge2 题解 要求的是串的不同的子串个数 两道一模一样的题 ...
- 【SPOJ】Distinct Substrings
[SPOJ]Distinct Substrings 求不同子串数量 统计每个点有效的字符串数量(第一次出现的) \(\sum\limits_{now=1}^{nod}now.longest-paren ...
- SPOJ 694. Distinct Substrings (后缀数组不相同的子串的个数)转
694. Distinct Substrings Problem code: DISUBSTR Given a string, we need to find the total number o ...
- SPOJ 694 Distinct Substrings
Distinct Substrings Time Limit: 1000ms Memory Limit: 262144KB This problem will be judged on SPOJ. O ...
- SPOJ 694 Distinct Substrings/SPOJ 705 New Distinct Substrings(后缀数组)
Given a string, we need to find the total number of its distinct substrings. Input T- number of test ...
- SPOJ - DISUBSTR Distinct Substrings (后缀数组)
Given a string, we need to find the total number of its distinct substrings. Input T- number of test ...
- SPOJ 705 Distinct Substrings(后缀数组)
[题目链接] http://www.spoj.com/problems/SUBST1/ [题目大意] 给出一个串,求出不相同的子串的个数. [题解] 对原串做一遍后缀数组,按照后缀的名次进行遍历, 每 ...
- spoj 694. Distinct Substrings 后缀数组求不同子串的个数
题目链接:http://www.spoj.com/problems/DISUBSTR/ 思路: 每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相同的前缀的个数.如果所有的后缀按照su ...
- 后缀数组 SPOJ 694 Distinct Substrings
题目链接 题意:给定一个字符串,求不相同的子串的个数 分析:我们能知道后缀之间相同的前缀的长度,如果所有的后缀按照 suffix(sa[0]), suffix(sa[1]), suffix(sa[2] ...
随机推荐
- 《Linux就该这么学》第二期视频
Linux就该这么学--第二期学习笔记... ------------- 你的未来取决于你现在点点滴滴的努力 需要用到的一些工具: Vm11激活码 ---------- root在Linux系统中相当 ...
- python---wsgiref初探
wsgiref使用 from wsgiref.simple_server import make_server from urls import URLS def RunServer(environ, ...
- idea创建多模块springboot项目
需求:一个父模块 下面几个子模块 其中一个模块是springboot结构.其他两个普通jar类型 有许多坑,都在注释里面写着呢.注意看父模块和demo模块的注释. com.imooc.securi ...
- C#多线程和异步(三)——一些异步编程模式
一.任务并行库 任务并行库(Task Parallel Library)是BCL中的一个类库,极大地简化了并行编程,Parallel常用的方法有For/ForEach/Invoke三个静态方法.在C# ...
- win2003服务器安全设置教程
服务器安全设置 1.系统盘和站点放置盘必须设置为NTFS格式,方便设置权限. 2.系统盘和站点放置盘除administrators 和system的用户权限全部去除. 3.启用windows自带防火墙 ...
- 运用Zabbix实现内网服务器状态及局域网状况监控(3) —— Zabbix服务端安装
1. Zabbix服务端安装,基于LNMP PHP5.5+Nginx1.9安装配置:http://www.cnblogs.com/vurtne-lu/p/7707536.html MySQL5.5编译 ...
- Redis(二)冰叔带你了解Redis-哨兵模式和高可用集群解析
前言 Redis 的 主从复制 模式下,一旦 主节点 由于故障不能提供服务,需要手动将 从节点 晋升为 主节点,同时还要通知 客户端 更新 主节点地址,这种故障处理方式从一定程度上是无法接受的. ...
- [C++]指针与引用(定义辨析)
1.定义: 1.1 &-----取地址运算符 功能:返变量的内存地址 Eg:int *p,m; 定义p为指向int类型变量的指针,同时定义变量m ...
- python yield from
def kk(): print (1) yield print (2) return 3 k=kk() def hello(k): print("Hello world!") r ...
- Java导出List集合到txt文件中——(四)
有时候,需要将数据以一定格式导出到txt文件中.利用Java的IO可以轻松的导出数据到txt中. package Action.txt; import java.io.BufferedWriter; ...