题目链接

Problem Description
Uncle Mao is a wonderful ACMER. One day he met an easy problem, but Uncle Mao was so lazy that he left the problem to you. I hope you can give him a solution.
Given a string s, we define a substring that happens exactly k times as an important string, and you need to find out how many substrings which are important strings.
 
Input
The first line contains an integer T (T≤100) implying the number of test cases.
For each test case, there are two lines:
the first line contains an integer k (k≥1) which is described above;
the second line contain a string s (length(s)≤105).
It's guaranteed that ∑length(s)≤2∗106.
 
Output
For each test case, print the number of the important substrings in a line.
 
Sample Input
2
2
abcabc
3
abcabcabcabc
 
Sample Output
6
9
 
 
题意:有一个字符串s,求其中恰好出现k次的子串有多少个?
 
思路:后缀数组,通过后缀数组算法可以知道每个后缀的排名,如果有某个子串恰好出现k次,那么必定有k个对应的后缀 即这个子串是这k个后缀串的前缀,那么这k个后缀串的排名一定是连续的,所以我们按排名从1~len(s)依次开始 取连续k个后缀串,可以根据height[]数组快速算出当前这k个后缀串的最大公共前缀长度len,那么长为1到len的前缀子串,这k个串都含有,设当前开始k个串为 i到i+k-1 ,那么如果子串长过短,可能 i-1 或 i+k 这个串也含有相应的子串,所以计算出 i 和 i-1 串,i+k和i+k-1的最大公共前缀长为m,那么之前取的子串长必须大于m才能保证 i-1 和 i+k 不含有相应的子串,只有i~i+k-1这k个串含有相应的子串。
 
代码如下:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long LL;
const int N=1e5+;
char s[N];
int k;
int wa[N],wb[N],wv[N],wss[N];
int sa[N],ran[N],height[N];
int f[N][]; int cmp(int *r,int a,int b,int l)
{
return r[a]==r[b]&&r[a+l]==r[b+l];
}
void da(char *r,int *sa,int n,int m)
{
int i,j,p,*x=wa,*y=wb,*t;
for(i=; i<m; i++) wss[i]=;
for(i=; i<n; i++) wss[x[i]=(int)r[i]]++;
for(i=; i<m; i++) wss[i]+=wss[i-];
for(i=n-; i>=; i--) sa[--wss[x[i]]]=i;
for(j=,p=; p<n; j*=,m=p)
{
for(p=,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<n; i++) wv[i]=x[y[i]];
for(i=; i<m; i++) wss[i]=;
for(i=; i<n; i++) wss[wv[i]]++;
for(i=; i<m; i++) wss[i]+=wss[i-];
for(i=n-; i>=; i--) sa[--wss[wv[i]]]=y[i]; for(t=x,x=y,y=t,p=,x[sa[]]=,i=; i<n; i++)
x[sa[i]]=cmp(y,sa[i-],sa[i],j)?p-:p++;
}
return;
}
void callheight(char *r,int *sa,int n)
{
int i,j,k=;
for(i=;i<=n;i++)
ran[sa[i]]=i;
for(i=;i<n;height[ran[i++]]=k)
for(k?k--:,j=sa[ran[i]-];r[i+k]==r[j+k];k++);
return ;
}
void init(int len)
{
for(int i=;i<=len;i++) f[i][]=height[i];
for(int s=;(<<s)<=len;s++)
{
int tmp=(<<s);
for(int i=;i+tmp-<=len;i++)
{
f[i][s]=min(f[i][s-],f[i+tmp/][s-]);
}
}
}
int cal(int l,int r)
{
int len=log2(r-l+);
int ans=min(f[l][len],f[r-(<<len)+][len]);
return ans;
}
int main()
{
int T; cin>>T;
while(T--)
{
scanf("%d%s",&k,s);
int len=strlen(s);
da(s,sa,len+,);
callheight(s,sa,len);
init(len);
int ans=;
for(int i=;i+k-<=len;i++)
{
int j=i+k-;
int tmp=height[i];
if(j+<=len) tmp=max(tmp,height[j+]);
int x;
if(k!=) { x=cal(i+,j); }
else x=len-sa[i];
ans+=max(,x-tmp);
}
printf("%d\n",ans);
}
return ;
}
 
 

hdu 6194 沈阳网络赛--string string string(后缀数组)的更多相关文章

  1. [2019CCPC网络赛][hdu6704]K-th occurrence(后缀数组&&主席树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6704 题意为查询子串s[l...r]第k次出现的位置. 写完博客后5分钟的更新 写完博客才发现这份代码 ...

  2. hdu 6199 沈阳网络赛---gems gems gems(DP)

    题目链接 Problem Description Now there are n gems, each of which has its own value. Alice and Bob play a ...

  3. 2018 ICPC 沈阳网络赛

    2018 ICPC 沈阳网络赛 Call of Accepted 题目描述:求一个算式的最大值与最小值. solution 按普通算式计算方法做,只不过要同时记住最大值和最小值而已. Convex H ...

  4. HDU 6194 string string string 2017沈阳网络赛 后缀数组

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6194 题意:告诉你一个字符串和k , 求这个字符串中有多少不同的子串恰好出现了k 次. 解法:后缀数组 ...

  5. 2019 徐州网络赛 G Colorful String 回文树

    题目链接:https://nanti.jisuanke.com/t/41389 The value of a string sss is equal to the number of differen ...

  6. HDU5008 Boring String Problem(后缀数组 + 二分 + 线段树)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5008 Description In this problem, you are given ...

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

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

  8. 沈阳网络赛 F - 上下界网络流

    "Oh, There is a bipartite graph.""Make it Fantastic." X wants to check whether a ...

  9. HDU 3948 The Number of Palindromes(Manacher+后缀数组)

    题意 求一个字符串中本质不同的回文子串的个数. $ 1\leq |string| \leq 100000$ 思路 好像是回文自动机的裸题,但是可以用 \(\text{Manacher}\) (马拉车) ...

随机推荐

  1. mysql导出指定字段或指定数据到文件中

    使用mysqldump把mysql数据库的数据导出到文件中还是挺方便的:比如说要导出baijunyao数据库: // mysqldump -u用户名 -p 数据库名 [表名]> 导出的文件名 m ...

  2. HDU 2202 最大三角形(凸包)

    Problem Description 老师在计算几何这门课上给Eddy布置了一道题目,题目是这样的:给定二维的平面上n个不同的点,要求在这些点里寻找三个点,使他们构成的三角形拥有的面积最大.Eddy ...

  3. Vue学习-01

    1.vue 学习 v-bind:title 数据绑定 v-if 判断显示或者隐藏 <div id="app-3"> <p v-if="seen" ...

  4. C# Process.Start()

    本文转自:http://webcache.googleusercontent.com/search?q=cache:v4Sh6GlfJPYJ:blog.csdn.net/czw2010/article ...

  5. vue指令v-if示例解析

    v-if根据表达式的值的真假条件渲染元素. <div id="app"> <p v-if="isRender">this is a me ...

  6. 安徽省2016“京胜杯”程序设计大赛_K_纸上谈兵

    纸上谈兵 Time Limit: 1000 MS Memory Limit: 65536 KB Total Submissions: 3 Accepted: 1 Description     战国时 ...

  7. Unity 坐标 转换 详解 World世界坐标 Screen屏幕坐标 View视口坐标 GUI坐标 NGUI坐标 localPosition相对父级坐标

    在制作游戏中我们经常会遇到这样一个需求: 在人物模型的上面显示 名字.称号 一类的文字或者图片 如下图 人物模型属于是Camera1   UI Title信息属于NGUI Camera2 如下图 这时 ...

  8. 页面嵌套frame,Selenium定位问题

    有时候,什么定位元素的方法都试过了,还是定位不到元素,就考虑frame切换问题 driver.switchTo().frame("定位到的frame元素"); //接下来就可以在这 ...

  9. Markdown几个简单的例子

    定义型列表 语法说明: 定义型列表由名词和解释组成.一行写上定义,紧跟一行写上解释. 解释的写法:紧跟一个缩进(Tab) Markdown : 轻量级文本标记语言,可以转换成html,pdf等格式(左 ...

  10. 查看oracle版本信息

    查看oracle的版本信息 (1)用客户端连接到数据库,执行select * from v$instance            查看version项 (2)select * from produc ...