【链接】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. Kinect 开发 —— 骨骼追踪(下)

    Kinect 连线游戏 在纸上将一些列数字(用一个圆点表示)从小到大用线连起来.游戏逻辑很简单,只不过我们在这里要实现的是动动手将这些点连起来,而不是用笔或者鼠标. 在开始写代码之前,需要明确定义我们 ...

  2. Kinect 开发 —— 深度信息

    转自:http://www.cnblogs.com/yangecnu/archive/2012/04/04/KinectSDK_Depth_Image_Processing_Part1.html 深度 ...

  3. Kinect 开发 —— 用户交互设计的若干思考

    Metro 风格 windows 8 Kinect Hub 手势原型设计 悬停选择     翻页控制 关节点重叠的处理方法 将箭靶设置在画面的边缘,这样玩家持弓的角度与屏幕保持一个大约45度的锐角,这 ...

  4. ArcSDE:C#创建SDE要素数据集

    转自原文 ArcSDE:C#创建SDE要素数据集 /// <summary> /// 判断指定数据集是否存在 /// </summary> /// <param name ...

  5. Linux网络编程--字节序

    1 .谈到字节序,那么会有朋友问什么是字节序 非常easy:[比如一个16位的整数.由2个字节组成,8位为一字节,有的系统会将高字节放在内存低的地址上,有的则将低字节放在内存高的地址上,所以存在字节序 ...

  6. JXL.jar简单封装Excel读写操作

    1.分析 一个excel文件能够有多页,每页excel中能够有多行,每行中能够有多列.用面向对象的思想能够把一行中的某列看作是一个String对象,一行看作是一个包括多个列的对象.一页是包括多行的对面 ...

  7. Windows简单入门-送给第一次使用电脑的朋友

    序言 写本篇文章前.不得不说我已经好久没有写博客了,快接近3个月了 吧,本来去年说參加今年的博客之星的,结果这都立即结束了:不得不说对自己有些嘲讽. 本篇文章是纯小白文章.之所以写这个是由于前段时间妹 ...

  8. hdu 1533 Going Home 最小费用最大流 入门题

    Going Home Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Tota ...

  9. 通俗理解vuex原理---通过vue例子类比

    本文主要通过简单的理解来解释下vuex的基本流程,而这也是vuex难点之一. 首先我们先了解下vuex的作用 vuex其实是集中的数据管理仓库,相当于数据库mongoDB,MySQL等,任何组件都可以 ...

  10. 洛谷 P1598 垂直柱状图

    P1598 垂直柱状图 题目描述 写一个程序从输入文件中去读取四行大写字母(全都是大写的,每行不超过72个字符),然后用柱状图输出每个字符在输入文件中出现的次数.严格地按照输出样例来安排你的输出格式. ...