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的更多相关文章

  1. 【SPOJ】Distinct Substrings(后缀自动机)

    [SPOJ]Distinct Substrings(后缀自动机) 题面 Vjudge 题意:求一个串的不同子串的数量 题解 对于这个串构建后缀自动机之后 我们知道每个串出现的次数就是\(right/e ...

  2. 【SPOJ】Distinct Substrings/New Distinct Substrings(后缀数组)

    [SPOJ]Distinct Substrings/New Distinct Substrings(后缀数组) 题面 Vjudge1 Vjudge2 题解 要求的是串的不同的子串个数 两道一模一样的题 ...

  3. 【SPOJ】Distinct Substrings

    [SPOJ]Distinct Substrings 求不同子串数量 统计每个点有效的字符串数量(第一次出现的) \(\sum\limits_{now=1}^{nod}now.longest-paren ...

  4. SPOJ 694. Distinct Substrings (后缀数组不相同的子串的个数)转

    694. Distinct Substrings Problem code: DISUBSTR   Given a string, we need to find the total number o ...

  5. SPOJ 694 Distinct Substrings

    Distinct Substrings Time Limit: 1000ms Memory Limit: 262144KB This problem will be judged on SPOJ. O ...

  6. 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 ...

  7. SPOJ - DISUBSTR Distinct Substrings (后缀数组)

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

  8. SPOJ 705 Distinct Substrings(后缀数组)

    [题目链接] http://www.spoj.com/problems/SUBST1/ [题目大意] 给出一个串,求出不相同的子串的个数. [题解] 对原串做一遍后缀数组,按照后缀的名次进行遍历, 每 ...

  9. spoj 694. Distinct Substrings 后缀数组求不同子串的个数

    题目链接:http://www.spoj.com/problems/DISUBSTR/ 思路: 每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相同的前缀的个数.如果所有的后缀按照su ...

  10. 后缀数组 SPOJ 694 Distinct Substrings

    题目链接 题意:给定一个字符串,求不相同的子串的个数 分析:我们能知道后缀之间相同的前缀的长度,如果所有的后缀按照 suffix(sa[0]), suffix(sa[1]), suffix(sa[2] ...

随机推荐

  1. Tomcat的配置文件详解

    Tomcat的配置文件详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Tomcat的配置文件 Tomcat的配置文件默认存放在$CATALINA_HOME/conf目录中, ...

  2. a超链接之返回顶部的两种实现方法

    1.通过css实现: 为页面顶部如body或者自己设置的盒子等加上唯一id属性 <body id="id"> .... <a href="#id&quo ...

  3. Hbase记录-ZooKeeper API

    Zookeeper API ZooKeeper有一个Java和C绑定的官方API.ZooKeeper社区提供了对于大多数语言(.NET,Python等)的非官方API.使用ZooKeeper的API, ...

  4. liunx必知必会(2)

    一.SSH免密登陆配置 1.相关概念 SSH 为 Secure Shell(安全外壳协议) 的缩写. 很多ftp.pop和telnet在本质上都是不安全的,因为它们在网络上用明文传送口令和数据,别有用 ...

  5. C语言指针详解(经典,非常详细)

    前言:复杂类型说明 要了解指针,多多少少会出现一些比较复杂的类型,所以我先介绍一下如何完全理解一个复杂类型,要理解复杂类型其实很简单,一个类型里会出现很多运算符,他们也像普通的表达式一样,有优先级,其 ...

  6. <T extends Comparable<? super T>>什么意思

    <T extends Comparable<? super T>>首先这是运用了java的泛型①extends后面跟的类型如<任意字符 extends 类/接口>表 ...

  7. Java编程思想 学习笔记12

    十二.通过异常处理错误  Java的基本理念是“结构不佳的代码不能运行”. Java中的异常处理的目的在于通过使用少于目前数量的代码来简化大型.可靠的程序的生成,并且通过这种方式可以使你更加自信:你的 ...

  8. 如何使用无线连接来使Android调试手机

    进入Android Studio.(我的是2.2版本) File->Setting->Plugins Browse repositories... 搜索 ADB WIFI 并安装 重启An ...

  9. Jacob 调用金税系统

    1.调用打印方法时,若是有预览弹窗提示,程序会阻塞住,并在控制台打印一行: C:\Program Files (x86)\��Ʊ���\914601007603699430.0\Config\Prin ...

  10. jaxp实现对xml文档的增,删,改,查操作(附源码)浅析

    jaxp,属于javase中的一部分.是对xml进行解析的一个工具类: 既然说到这里,还是讲全一点,讲讲上面说到的xml的解析技术. xml的一个标记型文档. 在html的层级结构中,它会在内存中分配 ...