Display Substring

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();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316278.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用 DotNet CLI 创建自定义的 WPF 项目模板

描述当我们安装完 DotNetCore 3.0 版本的 SDK 后&#xff0c;我们就可以创建基于 DotNetCore 的 WPF 项目模板&#xff0c;通过如下 CLI 可以方便快捷的创建并运行我们的项目&#xff1a;Copydotnet new wpf -n WpfAppcd WpfAppdotnet restoredotnet run做过 WPF 开发的朋友都知…

[省选联考 2020 A/B 卷] 信号传递(状压dp + 卡空间)

problem luogu-P6622 一条道路上从左至右排列着 mmm 个信号站&#xff0c;初始时从左至右依次编号为 1,2,…,m1,2,\dots,m1,2,…,m&#xff0c;相邻信号站之间相隔 111 单位长度。 每个信号站只能往它右侧的任意信号站传输信号&#xff08;称为普通传递&#xff09;&#xf…

SP687 REPEATS - Repeats(暂时不会)

SP687 REPEATS - Repeats 题意&#xff1a; 给定字符串&#xff0c;求重复次数最多的连续重复子串 题解&#xff1a; 论文题&#xff0c;暂时不会&#xff0c;搞不清楚原理 代码&#xff1a;

[翻译] ASP.NET Core 利用 Docker、ElasticSearch、Kibana 来记录日志

一步一步指导您使用 ElasticSearch, Kibana, ASP.NET Core 2.1 和 Docker 来记录日志在本教程中&#xff0c;我将向您展示如何启动和运行 ElasticSearch&#xff0c;Kibana 和 ASP.NET Core 2.1在开始之前&#xff0c;让我们来看看 ElasticSearch&#xff0c;Kibana 和 Serilog…

[省选联考 2020 A 卷] 作业题(欧拉反演 + 矩阵树定理 + 高斯消元)

problem luogu-P6624 小 W 刚刚在离散数学课学习了生成树的知识&#xff1a;一个无向图 G(V,E)G(V,E)G(V,E) 的生成树 TTT 为边集 EEE 的一个大小为 ∣V∣−1|V|-1∣V∣−1 的子集&#xff0c;且保证 TTT 的生成子图在 GGG 中连通。 小 W 在做今天的作业时被这样一道题目难住…

P4070 [SDOI2016]生成魔咒

P4070 [SDOI2016]生成魔咒 题意&#xff1a; 有n个字符xi&#xff0c;每次在S的末尾加入一个字符&#xff0c;(一开始S为空)&#xff0c;每次加入xi后的不相同字串有多少个 题解&#xff1a; 做这个题首先要会后缀数组P3809 【模板】后缀排序&#xff0c;还要知道不同的子串…

【学习笔记】WQS二分详解及常见理解误区解释

文章目录应用分析算法分析WQS二分精髓的两点细节&#xff08;博客重点&#xff01;&#xff09;真题分析[国家集训队]Tree Ⅰ忘情星际广播网上很多博客写得模模糊糊的&#xff0c;对我这个新手可是一点都不友好。 昨天一天都在研究这个东西&#xff0c;分享一下自己的拙见。 百…

ASP.NET Core中HTTP管道和中间件的二三事

本文出自《从零开始学ASP.NET CORE MVC》推荐文章&#xff1a;中间件是什么&#xff1f;在.NET Core中的工作原理又是怎样的呢&#xff1f;配置ASP.NET Core请求(Request)处理管道在本视频中&#xff0c;我们将讨论使用中间件组件为asp.net core 应用程序配置请求处理管道。作为…

Codeforces Round #737 (Div. 2)

Codeforces Round #737 (Div. 2) 题号题目知识点AEzzat and Two Subsequences思维&#xff08;略&#xff09;BMoamen and k-subarrays思维(略)CMoamen and XOR二进制DEzzat and Grid线段树思维EAssiut Chess

非平凡回路(bfs)

problem 题目描述 给定一张 nnn 个点的无向图&#xff0c;定义经过一个点 uuu 的非平凡回路为一条从 uuu 出发回到 uuu 的路径&#xff0c;并且至少包含一个简单环。 对于每个点求出经过它的最小非平凡回路长度 lll。 考虑到这个问题很困难&#xff0c;因此你只需要求出 ⌈…

cf1557 C. Moamen and XOR

cf1557 C. Moamen and XOR 题意&#xff1a; 一个n位数&#xff0c;每一位小于2k2^k2k,如果a1&a2&…an>a1⊕a2…⊕an,则获胜 现在给你n和k&#xff0c;问能构造多少个序列是获胜的 题解&#xff1a; 奇偶分类二进制考虑 我们现在认为每个数的第k位都是1 如果n为…

.Net Core Razor 预编译,动态编译,混合编译

预编译预编译是ASP .Net Core的默认方式。在发布时&#xff0c;默认会将系统中的所有Razor视图进行预编译。编译好的视图DLL统一命名为 xxx.PrecompiledViews.dll 或者 xxx.Views.dll动态编译将项目整个配置成动态编译很简单&#xff0c;添加一个配置项目MvcRazorCompileOnPubl…

[CodeForces gym 101630 J] 过路费(最短路)

problem 给定一张图 nnn 个点 mmm 条边&#xff0c;并给定阈值 kkk&#xff0c;以及起终点 s,ts,ts,t。 然后每条边经过都需要支付 www 的花费&#xff0c;形如 (u,v,w)(u,v,w)(u,v,w) 格式给出。 求 s→ts\rightarrow ts→t 的最小花费。 最小花费定义如下&#xff1a; 如…

cf1557D. Ezzat and Grid

cf1557D. Ezzat and Grid 题意&#xff1a; 有n行&#xff0c;每行有10910^9109列&#xff0c;仅仅由0和1构成 现在给你1的存在位置&#xff0c;(i,l,r)表示第i行的第l列到第r列全为1 你可以删除任意一行i&#xff0c;删除后&#xff0c;第i-1行和第i1行为相邻 现在我们要求求…

一张图来看看.NETCore和前后端技术的演进之路

一张图2019年3月10日&#xff0c;在长沙.NET 技术社区组织的技术沙龙《.NET Core和前后端分离那些事儿》上&#xff0c;我们曾经试图通过一系列抽丝剥茧的过程来引导大家在这条基于.NET Core的前后端分离有关的技术路线上持续发散&#xff0c;由于各种原因未能成功&#xff0c;…

【学习笔记】我命由天不由我之随机化庇佑 —— 爬山法 和 模拟退火法

以下均假设最优解是在最低点。 爬山法 爬山算法是一种局部择优的方法&#xff0c;采用启发式方法&#xff0c;是对深度优先搜索的一种改进&#xff0c;它利用反馈信息帮助生成解的决策。 直白地讲&#xff0c;就是当目前无法直接到达最优解&#xff0c;但是可以判断两个解哪…

Strange Memory Gym - 102832F

Strange Memory Gym - 102832F 题意&#xff1a; 有一颗n个节点的树&#xff0c;求下面公式的值&#xff1a; 题解&#xff1a; a ⊕ b c 可以推出a ⊕ c b 那么ai⊕ajalca(i,j)a_{lca(i,j)}alca(i,j)​,可以得到&#xff1a;ai⊕alca(i,j)a_{lca(i,j)}alca(i,j)​aj,ai就…

.net core 使用RSA获取私钥证书并签名

以前我们使用RSA加密主要是使用RSACryptoServiceProvider这个类&#xff0c;在.NET Core中也有这个类&#xff0c;但是这个类并不支持跨平台&#xff0c;所以如果你是用这个类来进行加/解密在windows上运行是完全没有错误的&#xff0c;但是只要你一放到Linux下就会出现异常。查…

2022 联合省选游记 信息奥赛五年退役记

Day0 这可不太美妙&#xff0c;十点就上床睡觉&#xff0c;结果完全睡不着&#xff0c;我妈打呼&#xff0c;加上我当时脑袋也想得多&#xff0c;整个人就挺烦躁的。 翻来覆去可能突然就睡着了&#xff0c;然后醒来虽然没天亮但是我猜至少也有五点多了吧&#xff0c;缓一会看…

CDN流量调度问题(2021CCPC华为云挑战赛)

CDN流量调度问题 题意&#xff1a; 有n个线路&#xff0c;每个线路的任务量为a[i],初始状态下&#xff0c;每个线路起初只有一个节点&#xff0c;每个线路完成任务所需时间为 现在你要给每个线路增加节点&#xff0c;所有增加的节点总数不超过m&#xff0c;第i个线路增加节点…