Problem

求字符串 S 中严格出现 k 次的子串个数

k≥1k\ge 1

|S|≤105|S|\le 10^5

∑|S|≤2×106\sum |S| \le 2\times 10^6

Idea

貌似很多队都是用后缀树 AC 的。好吧,我不会。


后缀数组 + 线段树 解法:

利用后缀数组处理出 height[] 数组,显然 height[i] 表示 sa[i]sa[i-1] 的最长公共前缀(LCP) 。

利用线段树或者 ST 表存储 height[] 数组,要求能够做的 O(1) or O(logn)\mathcal{O(1)} \text{ or } \mathcal{O(\log n)} 获取区间内最小的 height 。

按序枚举每一个 sa[i] ,显然有效子串的下界为 max(0,heighti,heighti+k)\max{(0, height_i, height_{i+k})} 。上界为 min(height[i+1,i+k−1])\min{(height[i+1, i+k-1])} (当 k=1 时,上界为 sa[i] 的长度)。在串长在上下界之间的所有 sa[i] 的前缀子串都对答案恭喜为 1 。

感觉不好写,直接甩手扔给队友… : )

Code

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int N = 100100;
int cmp(int *r,int a,int b,int l){return (r[a]==r[b]) && (r[a+l]==r[b+l]);
}
int wa[N],wb[N],wc[N],wv[N];
int Rank[N],height[N];
int mn[N<<2];
void DA(char *r,int *sa,int n,int m){int i,j,p,*x=wa,*y=wb,*t;for(i=0;i<m;i++) wc[i]=0;for(i=0;i<n;i++) wc[x[i]=r[i]]++;for(i=1;i<m;i++) wc[i]+=wc[i-1];for(i=n-1;i>=0;i--) sa[--wc[x[i]]]=i; for(j=1,p=1;p<n;j*=2,m=p) {for(p=0,i=n-j;i<n;i++) y[p++]=i; for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j; for(i=0;i<n;i++) wv[i]=x[y[i]];for(i=0;i<m;i++) wc[i]=0;for(i=0;i<n;i++) wc[wv[i]]++;for(i=1;i<m;i++) wc[i]+=wc[i-1];for(i=n-1;i>=0;i--) sa[--wc[wv[i]]]=y[i]; for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;  }
}
void calheight(char *r,int *sa,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]; r[i+k]==r[j+k]; k++);
}
void build(int l,int r,int rt){if(l==r){mn[rt]=height[l];return;}int mid=(l+r)>>1;build(l,mid,rt<<1);build(mid+1,r,rt<<1|1);mn[rt]=min(mn[rt<<1],mn[rt<<1|1]);
}
int query(int l,int r,int rt,int L,int R){if(L<=l && r<=R)return mn[rt];int mid=(l+r)>>1;int ret=1e9;if(mid>=L)ret=min(ret,query(l,mid,rt<<1,L,R));if(mid<R)ret=min(ret,query(mid+1,r,rt<<1|1,L,R));return ret;
}
char str[N];
int sa[N], nxt[N], T, k;
int main(){scanf("%d", &T);while(T--) {scanf("%d %s",&k,str);int n = strlen(str);str[n]=0;DA(str,sa,n+1,128);calheight(str,sa,n);build(1,n,1);LL ans=0;for(int i=1;i+k-1<=n;++i) {int len1;if(k>1)len1=query(1,n,1,i+1,i+k-1);elselen1=n-sa[i];int len2=0;if(i!=1)len2=max(len2,height[i]);if(i+k-1!=n)len2=max(len2,height[i+k]);if(len1>len2)ans+=len1-len2;}printf("%lld\n", ans);}
}

HDU 6194 String String String (后缀数组+线段树, 2017 ACM/ICPC Asia Regional Shenyang Online)相关推荐

  1. HDU - 6208 The Dominator of Strings n次KMP 2017 ACM/ICPC Asia Regional Qingdao Online

    找到最长串 然后进行n次KMP #include <iostream> #include <cstdio> #include <cstdlib> #include ...

  2. 2017 ACM/ICPC Asia Regional Shenyang Online Ping Ping Ping 树链剖分+树状数组

    原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=6203 题目大意:给出n+1个节点的树( 3<n<10^4),并给出m对点(m<=50 ...

  3. HDU 4069 Squiggly Sudoku(DLX)(The 36th ACM/ICPC Asia Regional Fuzhou Site —— Online Contest)...

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4069 Problem Description Today we play a squiggly sud ...

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

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

  5. hdu 5023 poj 2777(线段染色)2014 ACM/ICPC Asia Regional 广州 Online

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5023 http://poj.org/problem?id=2777 题意:给出一个长度为N的线段,分 ...

  6. HDU - 5493 Queue 2015 ACM/ICPC Asia Regional Hefei Online(线段树)

    按身高排序,每个人前面最高的人数有上限,如果超出上限说明impossible, 每次考虑最小的人,把他放在在当前的从左往右第k+1个空位 因为要求字典序最小,所以每次k和(上限-k)取min值. 没有 ...

  7. HDU 6194 string string string (后缀数组+线段树)

    题目https://cn.vjudge.net/problem/HDU-6194 没想到怎么用height数组求个数,看了看题解结合自己写的才明白, 妙啊. 我们按照height数组的特点,heigh ...

  8. hdu 4283 You Are the One ( dp 2012 ACM/ICPC Asia Regional Tianjin Online )

    http://acm.hdu.edu.cn/showproblem.php?pid=4283 题意: The TV shows such as You Are the One has been ver ...

  9. hdu 5444 Elven Postman(根据先序遍历和中序遍历求后序遍历)2015 ACM/ICPC Asia Regional Changchun Online...

    很坑的一道题,读了半天才读懂题,手忙脚乱的写完(套上模板+修改模板),然后RE到死-- 题意: 题面上告诉了我们这是一棵二叉树,然后告诉了我们它的先序遍历,然后,没了--没了! 反复读题,终于在偶然间 ...

最新文章

  1. SharePoint 2013/2010 中的日历重合 (Calendars Overlay)
  2. 十图详解TensorFlow数据读取机制(附代码)
  3. 找不到QtDir变量的解决办法, 同时不需要经过编译就可以使用qt 库
  4. armax函数 matlab 源码_将可读性不强的MATLAB公式样式转为直观的LaTeX样式
  5. imx6的kernel3.4.15启动流程
  6. python云变量_Python之变量的创建过程
  7. mybatis学习(11): sql server配置管理器请求失败或服务未及时响应
  8. 组合数学及其应用——polya计数
  9. 许可证编译器 (Lc.exe)
  10. Java8 in action(1) 通过行为参数化传递代码--lambda代替策略模式
  11. A2DP和AVRCP蓝牙音频传输协议
  12. 实对称矩阵的特征值求法_实对称矩阵、相似、标准型、合同的逻辑网
  13. 修改Eclipse字体以及背景颜色
  14. 【python中级】 获取系统的局域网ip地址
  15. 163VIP邮箱注册,163邮箱使用评价
  16. ptp精准时间协议_PTP时钟协议原理
  17. 旧金山州立大学计算机,旧金山州立大学(San-Francisco-State-University)_彬彬教育...
  18. 计算机系统基础书籍读后感,计算机系统基础试题.doc
  19. Android 项目集成有米 SDK 添加广告
  20. Linux命令基础入门

热门文章

  1. SQL server 清空数据库所有表
  2. ipa在线安装搭建_iOS12.4.1 越狱无法安装?教你百分百安装
  3. 名片管理系统 #python项目 #演练 #增删改查CRUD #全程教程
  4. 有没有什么大学生搜题比较好用的网站或APP
  5. 父类的对象指向子类对象,父类可以调用子类的方法吗?
  6. 几何变换详解:平移、缩放、旋转
  7. cad拖动有残影_LCD 残影问题分析及常见解决办法
  8. 安装tensorflow报错
  9. 算法导论 直接寻址表
  10. 字符串匹配 - Overview