【hdu 6194】string string string
【链接】h在这里写链接
【题意】
让你找出这个字符串里面,恰好出现了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
【错的次数】
【反思】
【代码】
#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的更多相关文章
- 【HDU 5030】Rabbit's String (二分+后缀数组)
Rabbit's String Problem Description Long long ago, there lived a lot of rabbits in the forest. One d ...
- 【HDU 6021】 MG loves string (枚举+容斥原理)
MG loves string Accepts: 30 Submissions: 67 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: ...
- 【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 ...
- 【HDOJ 1009】 CRB and String
[HDOJ 1009] CRB and String 每组两个串s t 仅仅由小写字母组成 问从s能不能变成t 改变的操作为选一个字符 在后面加上一个与所选字符不同的字符 这样的操作能够做无数次 问能 ...
- 【数位dp】【HDU 3555】【HDU 2089】数位DP入门题
[HDU 3555]原题直通车: 代码: // 31MS 900K 909 B G++ #include<iostream> #include<cstdio> #includ ...
- 【HDU 5647】DZY Loves Connecting(树DP)
pid=5647">[HDU 5647]DZY Loves Connecting(树DP) DZY Loves Connecting Time Limit: 4000/2000 MS ...
- -【线性基】【BZOJ 2460】【BZOJ 2115】【HDU 3949】
[把三道我做过的线性基题目放在一起总结一下,代码都挺简单,主要就是贪心思想和异或的高斯消元] [然后把网上的讲解归纳一下] 1.线性基: 若干数的线性基是一组数a1,a2,a3...an,其中ax的最 ...
- 【HDU 2196】 Computer(树的直径)
[HDU 2196] Computer(树的直径) 题链http://acm.hdu.edu.cn/showproblem.php?pid=2196 这题可以用树形DP解决,自然也可以用最直观的方法解 ...
- 【HDU 2196】 Computer (树形DP)
[HDU 2196] Computer 题链http://acm.hdu.edu.cn/showproblem.php?pid=2196 刘汝佳<算法竞赛入门经典>P282页留下了这个问题 ...
随机推荐
- ASP.Net MVC默认目录结构
1.Controllers 保存处理URL请求的Controller类 2.Models 保存操纵业务与数据对象的类 3.Views 保存UI模板页面 4.Scripts 保存Javascript库文 ...
- android图像处理(3) 底片效果
这篇将讲到图片特效处理的底片效果.跟前面一样是对像素点进行处理,算法是通用的. 算法原理:将当前像素点的RGB值分别与255之差后的值作为当前点的RGB值. 例: ABC 求B点的底片效果: B.r ...
- iOS-APP-Icon 图标启动图及名字的设置
本文讲下appIcon图标.启动图及名字的设置 icon for iOS 图标大小参照苹果官网:https://developer.apple.com/library/ios/qa/qa1686/_i ...
- oracle多实例的启动与关闭
Oracle/oracle登录 1.启监听器 lsnrctl start 监听一般不需要动,如果机器重新启动的话需要将监听启动. 查看当前SID:echo $ORACLE_SID 2.启动数据库实例: ...
- js39---组合模式,查找遍历树
/** *有这样一个需求 *有一个学校有2个班(一班,二班) *每个班级分2个小组(一班一组,一班二组,二班一组,二班二组) *学校计算机教室有限,每一个小组分着来上课. *考试的时候大家一起考 *请 ...
- js23---工厂模式1
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...
- android中图片倒影、圆角效果重绘
本文用来记录一些Android 操作图片的方法,方便查看. 1.将Drawable转化为Bitmap public static Bitmap drawableToBitmap(Drawable dr ...
- 38..Node.js工具模块---底层的网络通信--Net模块
转自:http://www.runoob.com/nodejs/nodejs-module-system.html Node.js Net 模块提供了一些用于底层的网络通信的小工具,包含了创建服务器/ ...
- $.post()提交了数据,return不给跳转
本来Controller接到普通请求,return “somePage”,这样就跳转了.前台用$.post()提交了数据(不需要回调),我了个大草,return那里就不给跳转了这样怎么解决? ajax ...
- JS数组排序技巧汇总(冒泡、sort、快速、希尔等排序)
本文实例总结了JS数组排序技巧.分享给大家供大家参考,具体如下: 1.冒泡排序 var temp = 0; for (var i = 0; i < array.length; i++) { fo ...