Repeated Substrings

Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu

Description

String analysis often arises in applications from biology and chemistry, such as the study of DNA and protein molecules. One interesting problem is to find how many substrings are repeated (at least twice) in a long string. In this problem, you will write a program to find the total number of repeated substrings in a string of at most 100 000 alphabetic characters. Any unique substring that occurs more than once is counted. As an example, if the string is “aabaab”, there are 5 repeated substrings: “a”, “aa”, “aab”, “ab”, “b”. If the string is “aaaaa”, the repeated substrings are “a”, “aa”, “aaa”, “aaaa”. Note that repeated occurrences of a substring may overlap (e.g. “aaaa” in the second case).

Input

The input consists of at most 10 cases. The first line contains a positive integer, specifying the number of
cases to follow. Each of the following line contains a nonempty string of up to 100 000 alphabetic characters.

Output

For each line of input, output one line containing the number of unique substrings that are repeated. You
may assume that the correct answer fits in a signed 32-bit integer.

Sample Input

3
aabaab
aaaaa
AaAaA

Sample Output

5
4
5

HINT

 

Source

解题:后缀数组lcp的应用,如果lcp[i] > lcp[i-1]那么累加lcp[i] - lcp[i-1]

 #include <bits/stdc++.h>
using namespace std;
const int maxn = ;
int rk[maxn],wb[maxn],wv[maxn],wd[maxn],lcp[maxn];
bool cmp(int *r,int i,int j,int k) {
return r[i] == r[j] && r[i+k] == r[j+k];
}
void da(int *r,int *sa,int n,int m) {
int i,k,p,*x = rk,*y = wb;
for(i = ; i < m; ++i) wd[i] = ;
for(i = ; i < n; ++i) wd[x[i] = r[i]]++;
for(i = ; i < m; ++i) wd[i] += wd[i-];
for(i = n-; i >= ; --i) sa[--wd[x[i]]] = i; for(p = k = ; p < n; k <<= ,m = p) {
for(p = ,i = n-k; i < n; ++i) y[p++] = i;
for(i = ; i < n; ++i) if(sa[i] >= k) y[p++] = sa[i] - k;
for(i = ; i < n; ++i) wv[i] = x[y[i]]; for(i = ; i < m; ++i) wd[i] = ;
for(i = ; i < n; ++i) wd[wv[i]]++;
for(i = ; i < m; ++i) wd[i] += wd[i-];
for(i = n-; i >= ; --i) sa[--wd[wv[i]]] = y[i]; swap(x,y);
x[sa[]] = ;
for(p = i = ; i < n; ++i)
x[sa[i]] = cmp(y,sa[i-],sa[i],k)?p-:p++;
}
}
void calcp(int *r,int *sa,int n) {
for(int i = ; i <= n; ++i) rk[sa[i]] = i;
int h = ;
for(int i = ; i < n; ++i) {
if(h > ) h--;
for(int j = sa[rk[i]-]; i+h < n && j+h < n; h++)
if(r[i+h] != r[j+h]) break;
lcp[rk[i]] = h;
}
}
int r[maxn],sa[maxn];
char str[maxn];
int main() {
int hn,x,y,cs,ret;
scanf("%d",&cs);
while(cs--) {
scanf("%s",str);
int len = strlen(str);
for(int i = ; str[i]; ++i)
r[i] = str[i];
ret = r[len] = ;
da(r,sa,len+,);
calcp(r,sa,len);
for(int i = ; i <= len; ++i)
if(lcp[i] > lcp[i-]) ret += lcp[i] - lcp[i-];
printf("%d\n",ret);
}
return ;
}

后缀自动机

 #include <bits/stdc++.h>
using namespace std;
const int maxn = ;
int cnt[maxn],c[maxn],sa[maxn];
struct node{
int son[],f,len;
void init(){
memset(son,-,sizeof son);
f = -;
len = ;
}
};
struct SAM{
node e[maxn];
int tot,last;
int newnode(int len = ){
e[tot].init();
e[tot].len = len;
return tot++;
}
void init(){
tot = last = ;
newnode();
}
void add(int c){
int p = last,np = newnode(e[p].len + );
while(p != - && e[p].son[c] == -){
e[p].son[c] = np;
p = e[p].f;
}
if(p == -) e[np].f = ;
else{
int q = e[p].son[c];
if(e[p].len + == e[q].len) e[np].f = q;
else{
int nq = newnode();
e[nq] = e[q];
e[nq].len = e[p].len + ;
e[q].f = e[np].f = nq;
while(p != - && e[p].son[c] == q){
e[p].son[c] = nq;
p = e[p].f;
}
}
}
last = np;
cnt[np] = ;
}
}sam;
char str[maxn];
int main(){
int kase;
scanf("%d",&kase);
while(kase--){
scanf("%s",str);
sam.init();
memset(cnt,,sizeof cnt);
int len = strlen(str);
for(int i = ; str[i]; ++i)
sam.add(str[i]);
node *e = sam.e;
memset(c,,sizeof c);
for(int i = ; i < sam.tot; ++i) c[e[i].len]++;
for(int i = ; i <= len; ++i) c[i] += c[i-];
for(int i = sam.tot-; i >= ; --i) sa[--c[e[i].len]] = i;
for(int i = sam.tot-; i > ; --i){
int v = sa[i];
cnt[e[v].f] += cnt[v];
}
int ret = ;
for(int i = ; i < sam.tot; ++i){
if(cnt[i] <= ) continue;
ret += e[i].len - e[e[i].f].len;
}
printf("%d\n",ret);
}
return ;
}

UVALive 6869 Repeated Substrings的更多相关文章

  1. UVALive - 6869 Repeated Substrings 后缀数组

    题目链接: http://acm.hust.edu.cn/vjudge/problem/113725 Repeated Substrings Time Limit: 3000MS 样例 sample ...

  2. CSU-1632 Repeated Substrings (后缀数组)

    Description String analysis often arises in applications from biology and chemistry, such as the stu ...

  3. UVALive 6869(后缀数组)

    传送门:Repeated Substrings 题意:给定一个字符串,求至少重复一次的不同子串个数. 分析:模拟写出子符串后缀并排好序可以发现,每次出现新的重复子串个数都是由现在的height值减去前 ...

  4. Repeated Substrings(UVAlive 6869)

    题意:求出现过两次以上的不同子串有多少种. /* 用后缀数组求出height[]数组,然后扫一遍, 发现height[i]-height[i-1]>=0,就ans+=height[i]-heig ...

  5. UVALive 4671 K-neighbor substrings 巧用FFT

    UVALive4671   K-neighbor substrings   给定一个两个字符串A和B B为模式串.问A中有多少不同子串与B的距离小于k 所谓距离就是不同位的个数. 由于字符串只包含a和 ...

  6. UVALive - 4671 K-neighbor substrings (FFT+哈希)

    题意:海明距离的定义:两个相同长度的字符串中不同的字符数.现给出母串A和模式串B,求A中有多少与B海明距离<=k的不同子串 分析:将字符a视作1,b视作0.则A与B中都是a的位置乘积是1.现将B ...

  7. CSU-1632 Repeated Substrings[后缀数组求重复出现的子串数目]

    评测地址:https://cn.vjudge.net/problem/CSU-1632 Description 求字符串中所有出现至少2次的子串个数 Input 第一行为一整数T(T<=10)表 ...

  8. LeetCode 1100. Find K-Length Substrings With No Repeated Characters

    原题链接在这里:https://leetcode.com/problems/find-k-length-substrings-with-no-repeated-characters/ 题目: Give ...

  9. [LeetCode] Repeated DNA Sequences 求重复的DNA序列

    All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for example: "ACG ...

随机推荐

  1. jsoncpp-src-0.5.0.tar.gz 源码错误!!!!

    近期在做毕设,使用到了JsonCpp0.5.0版本号的源码! 依照网上的安装配置教程,搭建好环境后就能够使用了! 在这里就不浪费空间去将怎样搭建开发环境了!请大家去google一下就好了! 在解析一个 ...

  2. 直接插入排序(Straight Insertion Sort)

    直接插入排序(Straight Insertion Sort)的基本操作是将一个记录插入到已经排好序的有序表中,从而得到一个新的.记录数增1的有序表. /* 对顺序表L作直接插入排序 */ void ...

  3. 【DNN引用包】

    <%@ Register TagPrefix="dnn" TagName="address" Src="~/controls/address.a ...

  4. vue中Object.defineProperty用法

    function def (obj, key, val, enumerable) { Object.defineProperty(obj, key, { value: val, enumerable: ...

  5. c# 枚举enum

    1 定义枚举 enum Days { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday }; 默认情况下,枚举中的每个元素的 ...

  6. Linux-CentOS5/6启动流程

    Linux-CentOS5/6启动流程

  7. 1x1卷积核作用

    1. 实现跨通道的交互和信息整合 对于某个卷积层,无论输入图像有多少个通道,输出图像通道数总是等于卷积核数量! 对多通道图像做1x1卷积,其实就是将输入图像于每个通道乘以卷积系数后加在一起,即相当于把 ...

  8. Linux/Mac vi命令详解

    刚开始学着用Linux,对vi命令不是很熟,在网上转接了一篇. vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器,这里只是简单地介绍一下它的用法和一小部分指 ...

  9. 旧机器安装ArchLinux的各种问题

    昨天突然想到家里还有一台很早之前不用的计算机 于是打算安装一个linux,开学再拿到宿舍用来写代码,怎么说台式机显示屏也比笔记本的大 机器安装问题 屏幕机箱擦干净,该连的东西都连上,然后插电源,本以为 ...

  10. 据统计WIN10用户已经比WIN7多

    数据统计机构Netmarketshare今天发布了2018年12月份最新的桌面操作系统份额报告.在看似无休止的等待之后,微软在2018年取得了最后的胜利,不仅成为市值最高的公司,而且最新的Window ...