Substring

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 485    Accepted Submission(s): 202

Problem Description
?? is practicing his program skill, and now he is given a string, he has to calculate the total number of its distinct substrings.
But ?? thinks that is too easy, he wants to make this problem more interesting.
?? likes a character X very much, so he wants to know the number of distinct substrings which contains at least one X.
However, ?? is unable to solve it, please help him.
Input
The first line of the input gives the number of test cases T;T test cases follow.
Each test case is consist of 2 lines:
First line is a character X, and second line is a string S.
X is a lowercase letter, and S contains lowercase letters(‘a’-‘z’) only.

T<=30
1<=|S|<=10^5
The sum of |S| in all the test cases is no more than 700,000.

Output
For each test case, output one line containing “Case #x: y”(without quotes), where x is the test case number(starting from 1) and y is the answer you get for that case.
Sample Input
2 a abc b bbb
Sample Output
Case #1: 3 Case #2: 3

Hint

In first case, all distinct substrings containing at least one a: a, ab, abc. In second case, all distinct substrings containing at least one b: b, bb, bbb.

题意:给你一个字符和一个字符串,问你字符串中包含这个字符的不同子串的个数。

分析:求出所有后缀后边最近的要求字符的位置f[i],对于后缀sa[i],对答案的贡献就是n - max(sa[i]+height[i],f[sa[i]])。

#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
//rank从0开始
//sa从1开始,因为最后一个字符(最小的)排在第0位
//height从2开始,因为表示的是sa[i-1]和sa[i]
const int MAXN = 100005;
int T,n,m,Rank[MAXN],sa[MAXN],X[MAXN],Y[MAXN],height[MAXN],s[MAXN],f[MAXN];
int buc[MAXN];
char str[MAXN],C[2];
void calheight(int n)
{int i , j , k = 0;for(i = 1 ; i <= n ; i++) Rank[sa[i]] = i;for(i = 0 ; i < n ; height[Rank[i++]] = k)for(k?k--:0 , j = sa[Rank[i]-1] ; s[i+k] == s[j+k] ; k++);
}
bool cmp(int *r,int a,int b,int l)
{return (r[a] == r[b] && r[a+l] == r[b+l]);
}
void suffix(int n,int m = 128)
{int i , l , p , *x = X , *y = Y;for(i = 0 ; i < m ; i ++) buc[i] = 0;for(i = 0 ; i < n ; i ++) buc[ x[i] = s[i]  ] ++;for(i = 1 ; i < m ; i ++) buc[i] += buc[i-1];for(i = n - 1; i >= 0 ; i --) sa[ --buc[ x[i] ]] = i;for(l = 1,p = 1 ; p < n ; m = p , l *= 2) {p = 0;for(i = n-l ; i < n ; i ++) y[p++] = i;for(i = 0 ; i < n ; i ++) if(sa[i] >= l) y[p++] = sa[i] - l;for(i = 0 ; i < m ; i ++) buc[i] = 0;for(i = 0 ; i < n ; i ++) buc[ x[y[i]] ] ++;for(i = 1 ; i < m ; i ++) buc[i] += buc[i-1];for(i = n - 1; i >= 0 ; i --) sa[ --buc[ x[y[i]] ] ] = y[i];for(swap(x,y) , x[sa[0]] = 0 , i = 1 , p = 1 ; i < n ; i ++)x[ sa[i] ] = cmp(y,sa[i-1],sa[i],l) ? p-1 : p++;}calheight(n-1);//后缀数组关键是求出height,所以求sa的时候顺便把rank和height求出来
}
int main()
{scanf("%d",&T);for(int t = 1;t <= T;t++){scanf("%s",C);scanf("%s",str);int n = strlen(str);for(int i = 0;i < n;i++) s[i] = str[i];s[n] = 0;int now = n;for(int i = n-1;i >= 0;i--){if(str[i] == C[0]) now = i;f[i] = now;}suffix(n+1,128);long long tot = 1ll*n - max(sa[1],f[sa[1]]);for(int i = 2;i <= n;i++) tot += 1ll*n - max(sa[i]+height[i],f[sa[i]]);printf("Case #%d: %I64d\n",t,tot);}
}

Hdu-5769 Substring (SA后缀数组)相关推荐

  1. HDU 5769 Substring(后缀数组)

    Substring Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total ...

  2. HDU - 5769 Substring(后缀数组)

    题目链接:点击查看 题目大意:给出一个字符串 s 和一个字符 ch,问字符串 s 中有多少个本质不同的子串包含字符 ch 题目分析:其实就是求本质不同的子串加了一点条件,对于每个sa[ i ],其本质 ...

  3. sa后缀数组使用合集,包括height数组求LPC和LCS,ST表,单调队列优化。

    P5546 [POI2000]公共串 所有串合在一起,每两个串放不同的字符,求一遍后缀数组,然后利用height数组求LCS即可. #include<iostream> #include& ...

  4. HDU 5769 Substring

    后缀数组. 然后按照排序完成之后的顺序,每个后缀统计贡献量. 统计第i个后缀的贡献的时候,如果这个后缀中没有X,贡献度为0. 有贡献的分3种情况考虑: 1.如果这个后缀height部分等于0(即与前一 ...

  5. HDU - 6704 K-th occurrence (后缀数组+主席树)

    题目链接 题意 QQQ次询问,每次询问求SSS的子串出现KKK次的位置 思路 刚开始想的是AC自动机,但是建自动机会超时,后来学长想到后缀数组+主席树的做法Orz...Orz...Orz... 出现K ...

  6. HDU - 3518 Boring counting(后缀数组)

    题目链接:点击查看 题目大意:给出一个字符串,问有多少个子串出现了两次以上,计算时彼此不能覆盖 题目分析:因为数据范围比较小,我们可以直接暴力,枚举子串的长度,利用height数组的性质将后缀分为不同 ...

  7. 2021“MINIEYE杯”中国大学生算法设计超级联赛(4)Display Substring(后缀数组+二分)

    Display Substring #include<bits/stdc++.h> using namespace std; typedef long long ll; // sa[i]: ...

  8. POJ 3693 Maximum repetition substring (后缀数组)

    题目大意: 求出字典序最小,重复次数最多,的子串. 思路分析: RMQ + height 数组可以求出任意两个后缀的lcp 我们枚举答案字符串的重复的长度. 如果这个字符串的长度为 l ,而且这个字符 ...

  9. 字符串-后缀树和后缀数组详解

    文章目录 后缀树 后缀数组 概念 sa[] rk[] height[] 例题 HDU-1403最长公共子串 洛谷P2408 不同子串个数 HDU-5769Substring 后缀树 建议先了解一下字典 ...

  10. 后缀数组(未完待续)

    后缀数组 简介 后缀数组(Suffix Array, SA)是一种在字符串问题中很实用的工具,其主要作用是求多模板匹配和最长公共前缀(LCP).与 AC自动机 预先处理模板串不同,后缀数组在进行多模板 ...

最新文章

  1. legend3---lavarel多对多模型操作实例
  2. 并发测试mysql_实践100个线程:一次MySQL数据并发问题
  3. java pdf 书签_Java 展开或折叠PDF中的书签
  4. 关于Oracle数据库中行迁移/行链接的问题(一)
  5. Codeforce-CodeCraft-20 (Div. 2)-B. String Modification (找规律+模拟)
  6. EF Core 3 的 40 个中断性变更
  7. RxJava + Java8 + Java EE 7 + Arquillian =幸福
  8. 转:Fiddler抓包工具总结
  9. Linux之强大的selinux
  10. STL常用函数总结-map
  11. checkout 撤销修改_撤销修改(第8篇)
  12. 量子加密技术成功在人工智能产品上的应用落地
  13. Revisiting Self-Training for Few-Shot Learning of Language Model
  14. html盒子里的图片居中,文本在盒子中水平、垂直居中(图片与文本居中)、多行文本垂直居中...
  15. 同步机制应遵循的准则
  16. 世界期货市场竞争格局的变迁
  17. 和平精英显示与服务器断开连接,和平精英网络异常怎么办 网络异常解决方法...
  18. Android中如何获取当前apn接入点并切换?
  19. Java之美[从菜鸟到高手演变]之Java学习方法
  20. 微信退款回调AES算法(AES-256-ECB)

热门文章

  1. 闲谈IPv6-IPv6的分片(IPv6 Fragment)
  2. 让excel窗口置顶(可以用于Win 64或者 Win 32)
  3. PHP框架高级编程——应用Symfony、CakePHP
  4. 将canvas生成图片或者签名背景透明变为白色背景
  5. HDU 2586 How far away ? tarjan算法求LCA
  6. Linux下使用alsamixer配置系统默认的声卡设备(默认音频输出设备、输入设备、系统音量)
  7. php源雄武,8个新鲜的PHP常用代码
  8. [转]中国象棋谚语大全
  9. 【AI视野·今日CV 计算机视觉论文速览 第187期 part1】Fri, 18 Dec 2020
  10. 绩效管理实务与管理效率提升-王晓耕老师