题目https://cn.vjudge.net/problem/HDU-6194

没想到怎么用height数组求个数,看了看题解结合自己写的才明白,

妙啊。

我们按照height数组的特点,height【i+1】到height【i+k-1】中的最小值便是在sa【i】 到sa【i+k-1】这k个后缀串中都出现过的子串长度,也就是说这个子串至少出现了k次,但是题目中要求这个子串必须标准出现k次,于是我们再看这子串有没有出现在sa【i-1】或者sa [i+k] 中,即看max(height【i-1】,heigh【i+k】),我们将出现了的减去,剩下的即是,标准出现k次的,如果小于0 的话说明当前区间没有满足要求的子串。

当k=1时,按照原来的办法求就不好求了,但是我们用同样的思路,先求一个当前满足要求的串的长度,那不就是 n - sa[i] 吗,然后按照同样的思路再减去 max(height【i-1】,heigh【i+k】)

借鉴https://blog.csdn.net/My_stage/article/details/77936442

代码如下:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN =  1e5+50;char s[MAXN];
int sa[MAXN],t[MAXN],t2[MAXN],c[MAXN],n;
int height[MAXN], rankk[MAXN];
void DA(int m)
{int i, *x = t, *y = t2;for ( i = 0; i < m; i++)        c[i] = 0;for ( i = 0; i < n; i++)        c[x[i] = s[i]]++;for ( i = 1; i < m; i++)  c[i] += c[i - 1];for (i = n - 1; i >= 0; i--)    sa[--c[x[i]]] = i;for (int k = 1; k <= n; k <<= 1){int p = 0;for (i = n - k; i < n; i++)y[p++] = i;for (i = 0; i < n; i++){if (sa[i] >= k)y[p++] = sa[i] - k;}for (i = 0; i < m; i++) c[i] = 0;for (i = 0; i < n; i++)c[x[y[i]]]++;for (i = 0; i < m; i++)c[i] += c[i - 1];for (i = n - 1; i >= 0; i--)sa[--c[x[y[i]]]] = y[i];swap(x, y);p = 1;  x[sa[0]] = 0;for (i = 1; i < n; i++){x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p++;}if (p >= n) break;m = p;}
}void getHeight()
{int i, j, k = 0;for (i = 0; i < n; i++) rankk[sa[i]] = i;for (i = 0; i < n; i++){if (k)  k--;j = sa[rankk[i] - 1];while (s[i + k] == s[j + k])  k++;height[rankk[i]] = k;}
}
int mi[MAXN<<2];void build(int rt,int l,int r)
{if(l == r){mi[rt]=height[l];return;}int mid =(l+r)>>1;build(rt<<1|1,mid+1,r);build(rt<<1,l,mid);mi[rt]=min(mi[rt<<1],mi[rt<<1|1]);
}int query(int ql,int qr,int l,int r,int rt)
{if(ql<=l && qr>=r)return mi[rt];int mid=(l+r)>>1;int ans=1e9;if(mid>=ql) ans= query(ql,qr,l,mid,rt<<1);if(mid<qr) ans=min(ans,query(ql,qr,mid+1,r,rt<<1|1));return ans;
}int main()
{int t,k;scanf("%d",&t);while(t--){scanf("%d",&k);scanf("%s",s);int len=strlen(s);n = len+1;DA(200);getHeight();build(1,1,len);height[len+1]=0;if(k>len){printf("0\n");continue;}int ans=0;if(k==1){for(int i=1; i<=len-k+1; i++){ans+=max(len-sa[i]-max(height[i],height[i+k]),0);}printf("%d\n",ans);continue;}for(int i=1; i+k-1<=len; i++){ans+=max(query(i+1,i+k-1,1,len,1)-max(height[i],height[i+k]),0);}printf("%d\n",ans);}return 0;
}

HDU 6194 string string string (后缀数组+线段树)相关推荐

  1. HDU 6194 String String String (后缀数组+线段树, 2017 ACM/ICPC Asia Regional Shenyang Online)

    Problem 求字符串 S 中严格出现 k 次的子串个数 k≥1k\ge 1 |S|≤105|S|\le 10^5 ∑|S|≤2×106\sum |S| \le 2\times 10^6 Idea ...

  2. CF-547E(Mike and Friends)后缀数组+线段树 AC自动机+DFS序+树状数组

    题目链接 题意 NNN个串,每次询问区间[L,R][L,R][L,R]中有多少子串SiS_iSi​ 思路 把NNN个串合成一个长字符串,对这个长字符串求后缀数组,包含SiS_iSi​的子串的heigh ...

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

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

  4. D-query SPOJ - DQUERY(求区间不同数的个数)(树状数组||线段树+离散)(主席树+在线)

    English Vietnamese Given a sequence of n numbers a1, a2, -, an and a number of d-queries. A d-query ...

  5. HDU5853 Jong Hyok and String(二分 + 后缀数组)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5853 Description Jong Hyok loves strings. One da ...

  6. HDU 1556 前缀和 树状数组 线段树

    解法一: a[i]表示以 i作为起点,对 i-n的气球全部上色的次数  对(start,end)区间上色 ++a[start] --a[end+1]抵消掉 end+1-n的部分 问题转换为求 a的前缀 ...

  7. HDU - 6183 Color it(动态开点线段树/树状数组套动态开点线段树)

    题目链接:点击查看 题目大意:给出一个二维平面坐标系,需要完成四种操作: 0:删除所有点 1 xycx\ y\ cx y c:在点 (x,y)(x,y)(x,y) 处添加颜色 ccc 2 xy1y2x ...

  8. HDU - 4552 怪盗基德的挑战书(后缀数组+RMQ/KMP+dp)

    题目链接:点击查看 题目大意:给出一个字符串,统计每个前缀在字符串中出现的次数之和 题目分析:可以直接先用后缀数组跑出来height,再用RMQ跑出来任意两个后缀的height,我们可以将题意转换为求 ...

  9. luoguP5108 仰望半月的夜空 [官方?]题解 后缀数组 / 后缀树 / 后缀自动机 + 线段树 / st表 + 二分...

    仰望半月的夜空 题解 可以的话,支持一下原作吧... 这道题数据很弱..... 因此各种乱搞估计都是能过的.... 算法一 暴力长度然后判断判断,复杂度\(O(n^3)\) 期望得分15分 算法二 通 ...

最新文章

  1. 一加7充电_刘作虎:一加7没有无线充电,Dash是最好的快充之一
  2. python怎么创建一个二维数组_python 创建二维数组的方法
  3. LeetCode 113. 路径总和 II(回溯)
  4. 科普 | “开放知识”的定义
  5. 渗透中Poc、Exp、Payload、Rce与Shellcode的区别
  6. cmd命令:批量创建文件夹
  7. 建立U盘免疫病毒文件_七夕小子_新浪博客
  8. 第一篇 外贸企业出口退税
  9. apm最高的记录_APM工具使用记录
  10. 我们什么时候需要函数隐藏
  11. js常用插件(三)之html2canvas生成海报
  12. python编写规范
  13. 7、对数组中下标为奇(偶)数的元素进行操作
  14. 按键精灵识别不出图片
  15. 严厉打击恶意劫持 百度移动搜索推出烽火算法2.0
  16. 中国银联mPOS通用技术安全分析和规范解读
  17. 计算机读书笔记10000,读书笔记:抓住1/10000的机会
  18. 【Linux】Linux多线程(上)
  19. 关于爱情 懂得珍惜就好!
  20. 东北大学操作系统实验三详解

热门文章

  1. 未来量子计算机运算速度,中国科学家实现 “量子霸权”,计算速度比超级计算机快100万亿倍...
  2. Handler原理讲解及源码分析
  3. python读取word文档中的图片_【Python 3 获取Word所有图片】
  4. 对称加密非对称加密混合加密
  5. 优秀产品经理的18种能力
  6. 网上订餐系统java论文_网上订餐系统的毕业设计
  7. 《白帽子讲Web安全》| 学习笔记之Web框架安全
  8. 微信开发平台应用签名修改多久之后才可以使用
  9. android在线签名sdk,Android 微信 SDK 签名问题
  10. POJ - 1849 Two(树的直径)