【链接】h在这里写链接


【题意】


给你一个字符串s以及一个整数k;

让你找出这个字符串里面,恰好出现了k次的子串的个数。

k>=1

【题解】


后缀数组题。

对于输入的字符串。求出它的Height数组。

然后预处理出ST表。

便于求区间的最小值。

然后顺序枚举后缀的排名i;

对于height数组。

height[i]实际上包括了两个后缀的信息了。

所以每次处理k-1个height数组。

弄一个k-1长的窗口。(k==1)分类讨论

顺序往右移动.

然后看看这个窗口里面height的最小值temp是多少。

这是至少出现了k次的一个字符串。(也即这段区域里面所有后缀的前temp个字符组成的相同子串)

接下来,就看看height[l]和height[r+1]里面的较大值temp1为多少。

如果比temp小的话。对答案贡献就为temp-temp1;

也即这段区域里面所有后缀的前temp1+1个字符、前temp1+2...前temp个字符组成的字符串

    都恰好出现了k次。

不会重复计算。

因为temp1<temp的话。

下一个窗口的temp就变小了。

它肯定最多为上一个框框的temp1;

则下一个窗口的所有后缀的最长公共前缀只能是前temp1个字符,而上一轮的计数是从前temp1+1个字符开始的。

显然不会有重复的部分。





对于k=1的情况,只不过那个窗口里的最小值。变成了固定的了。

就是这个后缀的长度len了。

然后看看heigh[i]和height

【错的次数】


0

【反思】


在这了写反思

【代码】

#include <bits/stdc++.h>
using namespace std; const int N = 1e5;
const int MAX_CHAR = 255;//每个数字的最大值。
char s[N + 10];//如果是数字,就写成int s[N+10]就好,从0开始存
int Sa[N + 10], T1[N + 10], T2[N + 10], C[N + 10];
int Height[N + 10], Rank[N + 10];
int n,k; const int MAXL = 18;//log2数组的最大长度
const int INF = 0x3f3f3f3f;//数值绝对值的最大值 struct abc {
int pre2[MAXL + 5], need[N + 10];
int fmax[N + 10][MAXL + 5], fmin[N + 10][MAXL + 5]; void init()
{
pre2[0] = 1;
for (int i = 1; i <= MAXL; i++)
{
pre2[i] = pre2[i - 1] << 1;
}
need[1] = 0; need[2] = 1;
int temp = 2;
for (int i = 3; i <= n; i++)//need[i]表示长度为i是2的多少次方,可以理解为[log2i]
if (pre2[temp] == i)
need[i] = need[i - 1] + 1, temp++;
else
need[i] = need[i - 1];
} void getst(int *a, int n)
{
memset(fmax, -INF, sizeof fmax);
memset(fmin, INF, sizeof fmin);
for (int i = 1; i <= n; i++)//下标从0开始就改成对应的就好
fmax[i][0] = fmin[i][0] = a[i]; for (int l = 1; pre2[l] <= n; l++)
for (int i = 1; i <= n; i++)
if (i + pre2[l] - 1 <= n)
fmax[i][l] = max(fmax[i][l - 1], fmax[i + pre2[l - 1]][l - 1]); for (int l = 1; pre2[l] <= n; l++)
for (int i = 1; i <= n; i++)
if (i + pre2[l] - 1 <= n)
fmin[i][l] = min(fmin[i][l - 1], fmin[i + pre2[l - 1]][l - 1]);
} int getmin(int l, int r)
{
int len = need[r - l + 1];
return min(fmin[l][len], fmin[r - pre2[len] + 1][len]);
} int getmax(int l, int r)
{
int len = need[r - l + 1];
return max(fmax[l][len], fmax[r - pre2[len] + 1][len]);
} }ST; void build_Sa(int n, int m) {
int i, *x = T1, *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 = 1; 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 n)
{
int i, j, k = 0;
for (i = 1; i <= n; i++) Rank[Sa[i]] = i;
for (i = 0; i<n; i++) {
if (k) k--;
j = Sa[Rank[i] - 1];
while (s[i + k] == s[j + k]) k++;
Height[Rank[i]] = k;
}
} int main()
{
//freopen("F:\\rush.txt", "r", stdin);
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d", &k);
scanf("%s", s);
n = strlen(s);
s[n] = 0;
build_Sa(n + 1, MAX_CHAR);
getHeight(n);
ST.init();
ST.getst(Height, n);
//按照k==1以及k!=1两种情况分一下类
long long ans = 0;
if (k == 1)
{
for (int i = 1; i <= n; i++)
{
int temp = n - Sa[i];
int temp1 = max(i == 1 ? 0 : Height[i], i == n ? 0 : Height[i + 1]);
if (temp > temp1)
ans += temp - temp1;
}
}
else
{
int l = 2;//左端点一开始等于l
for (int r = k; r <= n; r++)//枚举右端点在什么位置
{
//k-1个就凑够k次了
int temp = ST.getmin(l, r);//求出[l..r]的最小值
int temp1 = max(Height[l-1], r == n ? 0 : Height[r + 1]);
//l..r
//对应了
//l-1,l..r这些字符串
//Height[l-1]和Height[r+1] if (temp > temp1)
ans += temp - temp1;
l++;
}
}
printf("%lld\n", ans);
}
return 0;

【hdu 6194】string string string的更多相关文章

  1. 【HDU 5030】Rabbit's String (二分+后缀数组)

    Rabbit's String Problem Description Long long ago, there lived a lot of rabbits in the forest. One d ...

  2. 【HDU 6021】 MG loves string (枚举+容斥原理)

    MG loves string  Accepts: 30  Submissions: 67  Time Limit: 2000/1000 MS (Java/Others)  Memory Limit: ...

  3. 【HDU 3336】Count the string(KMP+DP)

    Problem Description It is well known that AekdyCoin is good at string problems as well as number the ...

  4. 【HDOJ 1009】 CRB and String

    [HDOJ 1009] CRB and String 每组两个串s t 仅仅由小写字母组成 问从s能不能变成t 改变的操作为选一个字符 在后面加上一个与所选字符不同的字符 这样的操作能够做无数次 问能 ...

  5. 【数位dp】【HDU 3555】【HDU 2089】数位DP入门题

    [HDU  3555]原题直通车: 代码: // 31MS 900K 909 B G++ #include<iostream> #include<cstdio> #includ ...

  6. 【HDU 5647】DZY Loves Connecting(树DP)

    pid=5647">[HDU 5647]DZY Loves Connecting(树DP) DZY Loves Connecting Time Limit: 4000/2000 MS ...

  7. -【线性基】【BZOJ 2460】【BZOJ 2115】【HDU 3949】

    [把三道我做过的线性基题目放在一起总结一下,代码都挺简单,主要就是贪心思想和异或的高斯消元] [然后把网上的讲解归纳一下] 1.线性基: 若干数的线性基是一组数a1,a2,a3...an,其中ax的最 ...

  8. 【HDU 2196】 Computer(树的直径)

    [HDU 2196] Computer(树的直径) 题链http://acm.hdu.edu.cn/showproblem.php?pid=2196 这题可以用树形DP解决,自然也可以用最直观的方法解 ...

  9. 【HDU 2196】 Computer (树形DP)

    [HDU 2196] Computer 题链http://acm.hdu.edu.cn/showproblem.php?pid=2196 刘汝佳<算法竞赛入门经典>P282页留下了这个问题 ...

随机推荐

  1. vim基础学习之自动补全功能

    本章我们学习自动补全功能1.自动补全优先从当前的编辑区获得补全列表例如:我们写下如下内容 aaaaa aabbb aaab 当我们再次输入aa,然后我们按下Tab的时候,会弹出一个包含 aaaaa a ...

  2. 通过Debug-->Attach to Process的方式来调试网站

    找到网站所对应的应用程序池

  3. c++中sizeof()的用法介绍

    1.      定义 sizeof是一个操作符(operator). 其作用是返回一个对象或类型所占的内存字节数. 2.      语法 sizeof有三种语法形式: 1)  sizeof (obje ...

  4. Mahout的推荐系统

    Mahout的推荐系统 什么是推荐系统 为什使用推荐系统 推荐系统中的算法 什么是推荐系统 为什么使用推荐系统? 促进厂商商品销售,帮助用户找到想要的商品 推荐系统无处不在,体现在生活的各个方面 图书 ...

  5. Android Studio 解决unspecified on project app resolves to an APK archive which is not supported

    出现该问题unspecified on project app resolves to an APK archive which is not supported as a compilation d ...

  6. 【转】BAT取当前日期的前一天

    ============================取前一天的日期       OK============================@echo off ::前一天的日期,格式化输出echo ...

  7. 【Django】认证系统

    目录 #. auth模块 1. 认证 authenticate() 2. 登陆 login(HttpRequest, user) 3. 注销 logout(request) 4. 认证判断 is_au ...

  8. dhclient---获取动态IP

    dhclient命令使用动态主机配置协议动态的配置网络接口的网络参数. 语法 dhclient(选项)(参数) 选项 0:指定dhcp客户端监听的端口号: -d:总是以前台方式运行程序: -q:安静模 ...

  9. Android学习笔记进阶十二之裁截图片

    package xiaosi.cut; import java.io.File; import android.app.Activity; import android.content.Intent; ...

  10. cluster discovery概述及FaultDetection分析

    elasticsearch cluster实现了自己发现机制zen.Discovery功能主要包括以下几部分内容:master选举,master错误探测,集群中其它节点探测,单播多播ping.本篇会首 ...