Display Substring

题意:

一个长度为n的字符串,每个字符有自己的价值,求第k小价值的不重复子串价值

题解:

首先众所周知,所有子串都可以用后缀的前缀来表示,这就和后缀数组扯上关系了
我们可以直接二分这个价值val,然后去算大于val的不重复子串有多少个(比如有x个),如果x大于k,说明该价值的情况下存在第k小价值,那r可以缩小,否则l可以增大,这是二分过程
那如果计算大于val的不重复子串有多少个,遍历后缀数组,对于每个后缀,如果其越长说明其价值越高,符合单调性,所有我们二分(没错二分套二分),二分找到价值小于等于val的值的前缀有多少个,再减去重复部分,看是否大于k,如果大于第一个二分就返回true
重复部分就是height数组对应的值,通过这题可以知道P2408 不同子串个数
注意height要和后缀二分出来的距离取min,因为要删除重复部分不能比这个字符串的长度还长

代码:

// Problem: Display Substring
// Contest: HDOJ
// URL: https://acm.hdu.edu.cn/showproblem.php?pid=6988
// Memory Limit: 262 MB
// Time Limit: 8000 ms
// Data:2021-08-22 17:57:49
// By Jozky#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\n", a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
void read(){};
template <typename _Tp, typename... _Tps> void read(_Tp& x, _Tps&... Ar)
{x= 0;char c= getchar();bool flag= 0;while (c < '0' || c > '9')flag|= (c == '-'), c= getchar();while (c >= '0' && c <= '9')x= (x << 3) + (x << 1) + (c ^ 48), c= getchar();if (flag)x= -x;read(Ar...);
}
template <typename T> inline void write(T x)
{if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0');
}
void rd_test()
{#ifdef LOCALstartTime= clock();freopen("in.txt", "r", stdin);
#endif
}
void Time_test()
{#ifdef LOCALendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
#endif
}
const int MAXN= 3e5;char ch[MAXN], all[MAXN];
int sa[MAXN], rk[MAXN], height[MAXN], tax[MAXN], tp[MAXN], a[MAXN], n, m;
char str[MAXN];
//rk[i] 第i个后缀的排名; sa[i] 排名为i的后缀位置; height[i] 排名为i的后缀与排名为(i-1)的后缀的LCP
//tax[i] 计数排序辅助数组; tp[i] rk的辅助数组(计数排序中的第二关键字),与sa意义一样。
//a为原串
void RSort()
{//rk第一关键字,tp第二关键字。for (int i= 0; i <= m; i++)tax[i]= 0;for (int i= 1; i <= n; i++)tax[rk[tp[i]]]++;for (int i= 1; i <= m; i++)tax[i]+= tax[i - 1];for (int i= n; i >= 1; i--)sa[tax[rk[tp[i]]]--]= tp[i]; //确保满足第一关键字的同时,再满足第二关键字的要求
} //计数排序,把新的二元组排序。int cmp(int* f, int x, int y, int w)
{return f[x] == f[y] && f[x + w] == f[y + w];
}
//通过二元组两个下标的比较,确定两个子串是否相同void Suffix()
{//safor (int i= 1; i <= n; i++)rk[i]= a[i], tp[i]= i;m= 127, RSort(); //一开始是以单个字符为单位,所以(m = 127)for (int w= 1, p= 1, i; p < n; w+= w, m= p) { //把子串长度翻倍,更新rk//w 当前一个子串的长度; m 当前离散后的排名种类数//当前的tp(第二关键字)可直接由上一次的sa的得到for (p= 0, i= n - w + 1; i <= n; i++)tp[++p]= i; //长度越界,第二关键字为0for (i= 1; i <= n; i++)if (sa[i] > w)tp[++p]= sa[i] - w;//更新sa值,并用tp暂时存下上一轮的rk(用于cmp比较)RSort(), swap(rk, tp), rk[sa[1]]= p= 1;//用已经完成的sa来更新与它互逆的rk,并离散rkfor (i= 2; i <= n; i++)rk[sa[i]]= cmp(tp, sa[i], sa[i - 1], w) ? p : ++p;}//离散:把相等的字符串的rk设为相同。//LCPint j, k= 0;for (int i= 1; i <= n; height[rk[i++]]= k)for (k= k ? k - 1 : k, j= sa[rk[i] - 1]; a[i + k] == a[j + k]; ++k);//这个知道原理后就比较好理解程序
}
ll k;
ll sum[MAXN];
ll val[MAXN];
inline void clear()
{memset(tax, 0, sizeof(tax));memset(sa, 0, sizeof(int) * (n + 1));memset(height, 0, sizeof(int) * (n + 1));memset(rk, 0, sizeof(int) * (n + 1));memset(sum, 0, sizeof(int) * (n + 1));memset(tp, 0, sizeof(int) * (n + 1));memset(a, 0, sizeof(int) * (n + 1));
}void Init()
{scanf("%d%lld", &n, &k);scanf("%s", str + 1);for (int i= 1; i <= n; i++)a[i]= str[i];// cout << (str + 1) << endl;for (int i= 1; i <= 26; i++)read(val[i]);for (int i= 1; i <= n; i++)sum[i]= sum[i - 1] + val[str[i] - 'a' + 1];
}
bool check(int x)
{ll ans= 0;for (int i= 1; i <= n; i++) {int l= sa[i], r= n;while (l < r) {int mid= (l + r + 1) >> 1;if (sum[mid] - sum[sa[i] - 1] <= x)l= mid;elser= mid - 1;}if (sum[l] - sum[sa[i] - 1] <= x) {ans+= l - sa[i] + 1;ans-= min(height[i], l - sa[i] + 1);}}return ans >= k;
}
int main()
{//rd_test();int t;read(t);while (t--) {clear();Init();Suffix();int l= 1, r= 0;for (int i= 1; i <= n; i++)r+= val[str[i] - 'a' + 1];// cout << "r=" << r << endl;while (l < r) {int mid= (l + r) >> 1;if (check(mid))r= mid;elsel= mid + 1;}if (!check(l))l= -1;printf("%d\n", l);}//Time_test();
}

Display Substring相关推荐

  1. 2021“MINIEYE杯”中国大学生算法设计超级联赛(4)Display Substring(后缀数组+二分)

    Display Substring #include<bits/stdc++.h> using namespace std; typedef long long ll; // sa[i]: ...

  2. HDU多校4 - 6988 Display Substring(后缀自动机+二分)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的字符串 sss,每个字母都有一个权值,现在要求所有本质不同子串中权值和第 kkk 大的权值 题目分析:如果没有本质不同,那有一个很简单的二分套二 ...

  3. 【2021杭电多校赛】2021“MINIEYE杯”中国大学生算法设计超级联赛(4)签到题4题

    Solved Pro.ID Title Ratio(Accepted / Submitted) 1001 Calculus 23.59%(852/3611) (数学,签到,结论) 1002 Kanad ...

  4. 【多校训练】2021HDU多校4

    [前言] 今天写题手感很好,写的都是1A,然而太蠢了做不动- - 开场自己切了三个水题,队友写了一个水题就开始搞不动了,后面就过了一个05. 字符串如此SB的东西都忘了,今天赶紧补回来了. rk53, ...

  5. java display.getdefault()_java基础(十一 )-----反射——Java高级开发必须懂的

    本文我们通过一个实际的例子来演示反射在编程中的应用,可能之前大家对反射的学习,仅仅是停留在概念层面,不知道反射究竟应用在哪,所以是一头雾水.相信通过这篇教程,会让你对反射有一个更深层次的认知. 概念 ...

  6. SAP-ABAP-SQL语句中CAST字段类型转换示例,CONCAT连接示例,SUBSTRING截断示例

    本文只针对S/4 HANA 1809 及更高版本有效. 话不多说,先上示例代码,然后再慢慢讲解 REPORT ZLQT_CAST.GET TIME STAMP FIELD DATA(timestamp ...

  7. Java substring使用时有哪些注意事项?

    首先,使用substring截取字符串时,可能会出现两种异常,分别是StringIndexOutOfBoundsException和NullPointerException. 即字符串索引越界异常 与 ...

  8. leetcode 30. Substring with Concatenation of All Words 与所有单词相关联的字串 滑动窗口法

    题目描述 给定一个字符串 s 和一些长度相同的单词 words.在 s 中找出可以恰好串联 words 中所有单词的子串的起始位置. You are given a string, s, and a ...

  9. leetcode Longest Substring with At Most Two Distinct Characters 滑动窗口法

    题目解析 代码如下 题目解析 这一题是一道会员的题目,题目介绍如下: Given a string, find the length of the longest substring T that c ...

最新文章

  1. 长连接及在Node中的应用——HTTP/1.1 keep-alive
  2. albian开发笔记五--谈缓存同步
  3. RHEL5下源码配置LAMP全记录
  4. 转 Python爬虫入门一之综述
  5. 怎么修改win11睡眠时间
  6. Maxcompute ODPS SQL 日期函数
  7. eclipse svn忽略指定文件或文件夹
  8. js 实现图片上传
  9. 抖音吸粉_抖音吸粉六大技巧
  10. 数据结构c语言版ppt答案,《数据结构(C语言版)》习题答案.ppt
  11. Windows 7 64位无法在状态码为0xc0000225的VirtualBox / Linux上安装
  12. 几何造型问题(转载)
  13. 电信光猫天翼网关usb插U盘共享文件
  14. Python面试题之数据类型
  15. 项目里用到的Jquery,json,struts2结合
  16. @Component和@Bean的区别
  17. 心理学导论--- 1 心理学在搞什么
  18. <input>标签构建快递信息界面(HTML+CSS)
  19. 雅思听力之高频词汇篇:全球地名
  20. 工程打包是什么意思_承包、发包、分包各是什么意思?

热门文章

  1. 超炫酷的枪械3D动图,喜欢的不得了!
  2. 长能耐了?想造反了?你老婆没了.......
  3. 如何把文件压缩变成一张图片?
  4. hadoop安装hive及配置mysql_Hadoop系列之Hive(数据仓库)安装配置
  5. 计算机硬件相关名词,计算机硬件基础名词解释
  6. request-promise 获取返回头信息_http返回的状态码 大全
  7. mysql 碎片率_MySQL数据碎片的整理和分析
  8. openkruise 缩容_Linus 本尊也来了!为什么 KubeCon 越来越火了?
  9. mysql数据库5120_超傻瓜 H3C S5120 限速配置
  10. pc 图片预览放大 端vue_安利一款简单好用的Vue图片预览插件