Distinct Substrings(后缀数组的运用&&高度数组的运用)

14人阅读 评论(0) 收藏 举报
分类:

题目链接

SPOJ-DISUBSTR

题意

给定一个字符串s,求s的所有子串不重复的个数。

分析

观察后缀数组,注意到子串一定是后缀数组中的后缀的前缀的一部分。即每一个后缀贡献len个子串(len是后缀的长度)。现在要去掉重复的子串,也就是去掉后缀的公共前缀,因为公共前缀贡献的子串是相同的。所以只需用所有的子串数减去公共前缀的长度和。

代码

#include <bits/stdc++.h>
#define rank ranka
using namespace std;
const int maxn=2e4+100;
int n,k,rank[maxn],tmp[maxn],sa[maxn],lcp[maxn];
string s;

bool cmp(int i,int j)
{
    if(rank[i]!=rank[j])
        return rank[i]<rank[j];
    else
    {
        int ri=i+k<=n?rank[i+k]:-1;
        int rj=j+k<=n?rank[j+k]:-1;
        return ri<rj;
    }
}
void get_sa()
{
    n=s.size();
    for(int i=0; i<=n; i++)
    {
        sa[i]=i;
        rank[i]=i<n?s[i]:-1;
    }
    for(k=1; k<=n; k*=2)
    {
        sort(sa,sa+n+1,cmp);
        tmp[sa[0]]=0;
        for(int i=1; i<=n; i++)
            tmp[sa[i]]=tmp[sa[i-1]]+(cmp(sa[i-1],sa[i])?1:0);
        for(int i=0; i<=n; i++)
            rank[i]=tmp[i];
    }

}
void get_lcp()
{
    for(int i=0; i<=n; i++)
        rank[sa[i]]=i;
    int h=0;
    lcp[0]=0;
    for(int i=0; i<n; i++)
    {
        int j=sa[rank[i]-1];
        if(h)
            h--;
        for(; i+h<n && j+h<n; h++)
            if(s[i+h]!=s[j+h])
                break;
        lcp[rank[i]-1]=h;
    }
}
int main()
{
    int N;
    cin>>N;
    while(N--)
    {
        cin>>s;
        get_sa();
        get_lcp();
        long long ans=(1+n)*n/2;
        for(int i=1;i<n;i++)
            ans-=lcp[i];
        cout<<ans<<endl;
    }
}

参考模板

高度数组模板
后缀数组模板

查看评论

SPOJ SUBST1 New Distinct Substrings 后缀数组-子串个数

#include #include using namespace std; const int maxn=200000; int t1[maxn],t2[maxn],c[maxn]; bool cm...
  • xinag578
  • xinag578
  • 2015-12-04 22:47:41
  • 205

后缀数组的倍增法实现

  • 2013年12月13日 20:24
  • 17KB
  • 下载

后缀数组之高度数组

加了一点自己对高度数组的理解: height 数组:定义 height[i]=suffix(sa[i-1])和 suffix(sa[i])的最长公共前缀,也就是排名相邻的两个后缀的最长公共前缀。那...
  • Mtrix
  • Mtrix
  • 2016-08-01 13:58:49
  • 1255

[POJ3415]Common Substrings(后缀数组+单调栈)

题目描述传送门 题意:给定两个字符串 A 和 B ,求长度不小于 k 的公共子串的个数(可以相同)。题解首先把一个串接在另一个串的后面,中间放一个没出现过的字符。 由于每一个子串都是某一个后缀的前...
  • Clove_unique
  • Clove_unique
  • 2016-12-26 21:20:13
  • 815

SPOJ DISUBSTR - Distinct Substrings 后缀数组,转化

DISUBSTR - Distinct Substrings no tags  Given a string, we need to find the total number...
  • Good_night_Sion_
  • Good_night_Sion_
  • 2017-04-14 09:00:56
  • 229

SPOJ - Distinct Substrings / SPOJ - New Distinct Substrings(后缀数组 - 不相同子串个数)

C - Distinct Substrings Time Limit:159MS     Memory Limit:1572864KB     64bit IO Format:%lld & %llu...
  • j6635788
  • j6635788
  • 2016-08-12 17:40:46
  • 204

SPOJ 题目694 Distinct Substrings(后缀数组,求不同的子串个数)

DISUBSTR - Distinct Substrings no tags  Given a string, we need to find the total number...
  • yu_ch_sh
  • yu_ch_sh
  • 2015-08-18 22:01:07
  • 500

SPOJ DISUBSTR - Distinct Substrings or SUBST1 - New Distinct Substrings 【不同子串数目】

题目链接:SPOJ DISUBSTR - Distinct Substrings DISUBSTR - Distinct Substrings no tags Given a string, ...
  • chenzhenyu123456
  • chenzhenyu123456
  • 2016-04-04 16:28:29
  • 379

Distinct Substrings 后缀数组

Given a string, we need to find the total number of its distinct substrings. Input T- number of te...
  • tianyuhang123
  • tianyuhang123
  • 2017-02-09 01:07:25
  • 155

【SPOJ-DISUBSTR】Distinct Substrings【后缀数组】

似乎还是例题? 求不同子串的个数。 用总的子串减去重复子串,总的子串个数为n * (n + 1) / 2,重复子串个数就是height的和。 (cnt又开小了,RE一次) #include...
  • BraketBN
  • BraketBN
  • 2016-02-10 11:02:08
  • 399
    个人资料
    持之以恒
    等级:
    访问量: 3264
    积分: 1142
    排名: 4万+
    文章存档