SPOJ - SUBST1 New Distinct Substrings —— 后缀数组 单个字符串的子串个数
题目链接:https://vjudge.net/problem/SPOJ-SUBST1
SUBST1 - New 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 <= 50000
Output
For each test case output one number saying the number of distinct substrings.
Example
- Input:
- 2
- CCCCC
- ABABA
- Output:
- 5
- 9
题意:
给出一个字符串,求这个字符串有多少种子串?
方法一:
方法二:
1.先不考虑重复的,那么长度为n的字符串,有n+(n-1)+……1 = n*(n+1)/2个子串。
2.然后再考虑重复出现的,即去重。利用后缀数组,求出height数组,那么减去∑height[i],即为答案。为何?
height[i]的定义:排名第i与排名第i-1的后缀的最长公共前缀。那么对于以sa[i](下标)为左端点的一群子串,最多有height[i]个是在以sa[i-1]为左端点的一群子串中出现过的,因此需要减去height[i]。并且排名相邻的子串,前缀的重叠率是最高的,因此不会出现遗漏。枚举每个height,即枚举每个左端点,即可减去所有重复出现的。
代码如下:
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- #include <vector>
- #include <cmath>
- #include <queue>
- #include <stack>
- #include <map>
- #include <string>
- #include <set>
- using namespace std;
- typedef long long LL;
- const double EPS = 1e-;
- const int INF = 2e9;
- const LL LNF = 9e18;
- const int MOD = 1e5;
- const int MAXN = 5e4+;
- bool cmp(int *r, int a, int b, int l)
- {
- return r[a]==r[b] && r[a+l]==r[b+l];
- }
- int t1[MAXN], t2[MAXN], c[MAXN];
- void DA(int str[], int sa[], int Rank[], int height[], int n, int m)
- {
- n++;
- int i, j, p, *x = t1, *y = t2;
- for(i = ; i<m; i++) c[i] = ;
- for(i = ; i<n; i++) c[x[i] = str[i]]++;
- for(i = ; i<m; i++) c[i] += c[i-];
- for(i = n-; i>=; i--) sa[--c[x[i]]] = i;
- for(j = ; j<=n; j <<= )
- {
- p = ;
- for(i = n-j; i<n; i++) y[p++] = i;
- for(i = ; i<n; i++) if(sa[i]>=j) y[p++] = sa[i]-j;
- for(i = ; i<m; i++) c[i] = ;
- for(i = ; i<n; i++) c[x[y[i]]]++;
- for(i = ; i<m; i++) c[i] += c[i-];
- for(i = n-; i>=; i--) sa[--c[x[y[i]]]] = y[i];
- swap(x, y);
- p = ; x[sa[]] = ;
- for(i = ; i<n; i++)
- x[sa[i]] = cmp(y, sa[i-], sa[i], j)?p-:p++;
- if(p>=n) break;
- m = p;
- }
- int k = ;
- n--;
- for(i = ; i<=n; i++) Rank[sa[i]] = i;
- for(i = ; i<n; i++)
- {
- if(k) k--;
- j = sa[Rank[i]-];
- while(str[i+k]==str[j+k]) k++;
- height[Rank[i]] = k;
- }
- }
- char str[MAXN];
- int r[MAXN], sa[MAXN], Rank[MAXN], height[MAXN];
- int main()
- {
- int T;
- scanf("%d", &T);
- while(T--)
- {
- scanf("%s", str);
- int len = strlen(str);
- for(int i = ; i<len; i++)
- r[i] = str[i];
- r[len] = ;
- DA(r, sa, Rank, height, len, );
- /* 方法一:
- LL ans = 0;
- for(int i = 1; i<=len; i++)
- ans += len-sa[i]-height[i];
- */
- // 方法二:
- LL ans = 1LL*len*(len+)/;
- for(int i = ; i<=len; i++)
- ans -= height[i];
- printf("%lld\n", ans);
- }
- }
SPOJ - SUBST1 New Distinct Substrings —— 后缀数组 单个字符串的子串个数的更多相关文章
- SPOJ 694 || 705 Distinct Substrings ( 后缀数组 && 不同子串的个数 )
题意 : 对于给出的串,输出其不同长度的子串的种类数 分析 : 有一个事实就是每一个子串必定是某一个后缀的前缀,换句话说就是每一个后缀的的每一个前缀都代表着一个子串,那么如何在这么多子串or后缀的前缀 ...
- POJ3415 Common Substrings —— 后缀数组 + 单调栈 公共子串个数
题目链接:https://vjudge.net/problem/POJ-3415 Common Substrings Time Limit: 5000MS Memory Limit: 65536K ...
- SPOJ SUBST1 New Distinct Substrings(后缀数组 本质不同子串个数)题解
题意: 问给定串有多少本质不同的子串? 思路: 子串必是某一后缀的前缀,假如是某一后缀\(sa[k]\),那么会有\(n - sa[k] + 1\)个前缀,但是其中有\(height[k]\)个和上一 ...
- SPOJ - DISUBSTR 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 后缀数组
题意:统计母串中包含多少不同的子串 然后这是09年论文<后缀数组——处理字符串的有力工具>中有介绍 公式如下: 原理就是加上新的,减去重的,这题是因为打多校才补的,只能说我是个垃圾 #in ...
- 后缀数组:SPOJ SUBST1 - New Distinct Substrings
Given a string, we need to find the total number of its distinct substrings. Input T- number of test ...
- 【SPOJ – SUBST1】New Distinct Substrings 后缀数组
New Distinct Substrings 题意 给出T个字符串,问每个字符串有多少个不同的子串. 思路 字符串所有子串,可以看做由所有后缀的前缀组成. 按照后缀排序,遍历后缀,每次新增的前缀就是 ...
- spoj Distinct Substrings 后缀数组
给定一个字符串,求不相同的子串的个数. 假如给字符串“ABA";排列的子串可能: A B A AB BA ABA 共3*(3+1)/2=6种; 后缀数组表示时: A ABA BA 对于A和 ...
- Spoj SUBST1 New Distinct Substrings
Given a string, we need to find the total number of its distinct substrings. Input T- number of test ...
随机推荐
- Spring3和Quartz2的应用实例
/** * 任务调度类 * @author Joyce.Luo * @date 2015-3-31 下午03:32:04 * @version V3.0 * @since Tomcat6.0,Jdk1 ...
- Android 使用意图播放本地视频
Android播放视频的方式有三种: 一.使用意图播放,调用本地安装的播放器,选择一个进行播放. 二.使用VideoView播放(VideoView事实上是对MediaPlayer的封装,使用起来非常 ...
- centos DHCP
yum install dhcp cat /usr/share/doc/dhcp-4.2.5/dhcpd.conf.example > /etc/dhcp/dhcpd.conf vim /etc ...
- Python例子二
例1.构造函数 #-*-coding:utf--*- import sys class Student: def __init__(self,name,age): self.__name=name s ...
- VMware-Fusion-7.0.0-2103067 Pro SN:序列号+ 百度云下载地址
VMware-Fusion-7.0.0-2103067Pro SN: 5CQE9-H5PY3-04ND5-4Z6EW-3QGDE JZCNC-2H9X9-44TD9-Y0X5W-2KGP5 8ZNTC ...
- Spring Cloud Zuul API服务网关之请求路由
目录 一.Zuul 介绍 二.构建Spring Cloud Zuul网关 构建网关 请求路由 请求过滤 三.路由详解 一.Zuul 介绍 通过前几篇文章的介绍,我们了解了Spring Cloud ...
- c# emit 实现类的代理
using System; using System.Linq; using System.Reflection; using System.Reflection.Emit; namespace Em ...
- jquery判断复选框是否被选中
$("#isUse").click(function(){ if($(this).is(':checked')){ $(this).attr('checked','checked' ...
- cocos2d-x 下使用加密 sqlite3
sqlite3 加密库用的是wxsqlite3-3.0.0.1 提取出来的, 在android 下測试通过,无异常 编译时仅仅须要编译 sqlite3secure.c 此文件,即能够成功.測试时生 ...
- alibaba canal安装笔记
canal是alibaba开源的基于mysql binlog解析工具,可利用它实现mysql增量订阅/消费,典型的应用场景如下图: 利用canal,可以将mysql的数据变化,通过解析binlog,投 ...