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. printf()格式化输出详解

    % - 0 m.n l或h 格式字符 下面对组成格式说明的各项加以说明: ①%:表示格式说明的起始符号,不可缺少. ②-:有-表示左对齐输出,如省略表示右对齐输出. ③0:有0表示指定空位填0,如省略 ...

  2. .Net MVC个人笔记

    关于转向的问题,目前知道的是Response.Redirect 和 location.href 我现在有两个controller,Home和Test <h2>this is Home< ...

  3. Linux命令之man

    man命令 用处:就是一个文档帮助手册 用法:在终端中输入man加上你想知道的命令,按Q退出man命令 示例: (我想知道pwd的用法) (我想知道ls命令的用法)

  4. search 重要文件路径 搜索【原】

    hosts文件路径 C:/WINDOWS/system32/drivers/etc/ tnsnames.ora文件路径 C:/oraclexe/app/oracle/product/11.2.0/se ...

  5. Study 1 —— Python简介

    Python与其他语言的区别C\C++:学习成本高,学习周期长,偏系统底层,在开发硬件驱动.嵌入式.游戏引擎开发等领域有广泛的应用:JAVA:目前使用最广泛的编程语言,第一个跨平台运行的语言,在大型E ...

  6. Spring RedisTemplate操作-注解缓存操作(11)

    @Service @CacheConfig(cacheNames="user") public class RedisAn { public Map<String, User ...

  7. cpu load过高问题排查

    load average的概念 top命令中load average显示的是最近1分钟.5分钟和15分钟的系统平均负载. 系统平均负载被定义为在特定时间间隔内运行队列中(在CPU上运行或者等待运行多少 ...

  8. Python官方操作Excel文档

    xlwt 1.3.0 Downloads ↓ Library to create spreadsheet files compatible with MS Excel 97/2000/XP/2003 ...

  9. php rsa理解

    参考链接:http://www.cnblogs.com/firstForEver/p/5803940.html 自己封装的一个类: <?php class CRsaAuthorization { ...

  10. F - Set of Strings

    You are given a string q. A sequence of k strings s1, s2, ..., sk is called beautiful, if the concat ...