2022-12-10:给你一个由小写字母组成的字符串 s ,和一个整数 k
如果满足下述条件,则可以将字符串 t 视作是 理想字符串 :
t 是字符串 s 的一个子序列。
t 中每两个 相邻 字母在字母表中位次的绝对差值小于或等于 k 。
返回 最长 理想字符串的长度。
字符串的子序列同样是一个字符串,并且子序列还满足:
可以经由其他字符串删除某些字符(也可以不删除)但不改变剩余字符的顺序得到。
注意:字母表顺序不会循环
例如,‘a’ 和 ‘z’ 在字母表中位次的绝对差值是 25,而不是 1 。

答案2022-12-10:

二维动态规划的解。
N为字符串长度,E为字符集大小,K为差值要求。
时间复杂度O(NE)。
空间复杂度O(N
E)。

一维动态规划从左往右递推版。
N为字符串长度,E为字符集大小,K为差值要求。
时间复杂度O(N*K)。
空间复杂度O(E)。

从左往右递推 + 线段树优化。
N为字符串长度,E为字符集大小,K为差值要求。
时间复杂度O(N * logE)。
空间复杂度O(E)。

代码用rust编写。代码如下:

use std::iter::repeat;
fn main() {
let s = "acfgbd";
let k = 2;
let ans = longest_ideal_string1(s, k);
println!("ans = {}", ans);
let ans = longest_ideal_string2(s, k);
println!("ans = {}", ans);
let ans = longest_ideal_string3(s, k);
println!("ans = {}", ans);
} // 二维动态规划的解
// N为字符串长度,E为字符集大小,K为差值要求
// 时间复杂度O(N*E)
// 空间复杂度O(N*E)
fn longest_ideal_string1(s: &str, k: i32) -> i32 {
let ss: Vec<char> = s.chars().collect();
let n = s.len() as i32;
let mut arr: Vec<i32> = repeat(0).take(n as usize).collect();
for i in 0..n {
arr[i as usize] = ss[i as usize] as i32 - 'a' as i32;
}
let mut dp: Vec<[i32; 27]> = repeat([-1; 27]).take(n as usize).collect();
return f(&mut arr, 0, 26, k, &mut dp);
}
fn get_max<T: Clone + Copy + std::cmp::PartialOrd>(a: T, b: T) -> T {
if a > b {
a
} else {
b
}
} fn get_min<T: Clone + Copy + std::cmp::PartialOrd>(a: T, b: T) -> T {
if a < b {
a
} else {
b
}
} // 数组s中所有的值都在0~25对应a~z
// 当前在s[i...]选择数字, 并且前一个数字是p
// 如果p<26,说明选择的前一个数字是p
// 如果p==26,说明之前没有选过任何数字
// 返回在前一个数字是p的情况下,在s[i...]上选择数字,最长理想子序列能是多长
// dp仅仅是缓存结构,暴力递归改动态规划常规技巧
fn f(s: &mut Vec<i32>, i: i32, p: i32, k: i32, dp: &mut Vec<[i32; 27]>) -> i32 {
if i == s.len() as i32 {
return 0;
}
if dp[i as usize][p as usize] != -1 {
return dp[i as usize][p as usize];
}
let p1 = f(s, i + 1, p, k, dp);
let mut p2 = 0;
if (p == 26 || i32::abs(s[i as usize] - p) <= k) {
p2 = 1 + f(s, i + 1, s[i as usize], k, dp);
}
let ans = get_max(p1, p2);
dp[i as usize][p as usize] = ans;
return ans;
} // 一维动态规划从左往右递推版
// N为字符串长度,E为字符集大小,K为差值要求
// 时间复杂度O(N*K)
// 空间复杂度O(E)
fn longest_ideal_string2(s: &str, k: i32) -> i32 {
let mut dp: [i32; 26] = [0; 26];
let mut c = 0;
let mut l = 0;
let mut r = 0;
let mut pre = 0;
let mut ans = 0;
let ss: Vec<char> = s.chars().collect();
for i in 0..ss.len() {
c = ss[i as usize] as i32 - 'a' as i32;
l = get_max(c - k, 0);
r = get_min(c + k, 25);
pre = 0;
for j in l..=r {
pre = get_max(pre, dp[j as usize]);
}
dp[c as usize] = 1 + pre;
ans = get_max(ans, dp[c as usize]);
}
return ans;
} // 从左往右递推 + 线段树优化
// N为字符串长度,E为字符集大小,K为差值要求
// 时间复杂度O(N * logE)
// 空间复杂度O(E)
fn longest_ideal_string3(s: &str, k: i32) -> i32 {
let ss: Vec<char> = s.chars().collect();
// 0 0 0
// 1(a) 2(b) ... 26(z)
let mut st = SegmentTree::new(26);
let mut c = 0;
let mut pre = 0;
let mut ans = 0;
for i in 0..ss.len() {
// i s.charAt(i)
// a 1
// b 2
// z 26
c = ss[i as usize] as i32 - 'a' as i32 + 1;
// 2 k = 3
// 1 2 3 4 5 6 7
// l = Math.max(c - k, 1)
// r = Math.min(c + k, 26)
pre = st.max(get_max(c - k, 1), get_min(c + k, 26));
ans = get_max(ans, 1 + pre);
st.update(c, 1 + pre);
}
return ans;
} struct SegmentTree {
n: i32,
max: Vec<i32>,
} impl SegmentTree {
fn new(maxSize: i32) -> Self {
let max: Vec<i32> = repeat(0).take(((maxSize + 1) << 2) as usize).collect();
SegmentTree {
n: maxSize + 1,
max,
}
}
fn update(&mut self, index: i32, c: i32) {
self.update0(index, index, c, 1, self.n, 1);
} fn max(&mut self, left: i32, right: i32) -> i32 {
return self.max0(left, right, 1, self.n, 1);
} fn pushUp(&mut self, rt: i32) {
self.max[rt as usize] = get_max(
self.max[(rt << 1) as usize],
self.max[(rt << 1 | 1) as usize],
);
} fn update0(&mut self, L: i32, R: i32, C: i32, l: i32, r: i32, rt: i32) {
if L <= l && r <= R {
self.max[rt as usize] = C;
return;
}
let mid = (l + r) >> 1;
if (L <= mid) {
self.update0(L, R, C, l, mid, rt << 1);
}
if (R > mid) {
self.update0(L, R, C, mid + 1, r, rt << 1 | 1);
}
self.pushUp(rt);
} fn max0(&mut self, L: i32, R: i32, l: i32, r: i32, rt: i32) -> i32 {
if L <= l && r <= R {
return self.max[rt as usize];
}
let mut mid = (l + r) >> 1;
let mut ans = 0;
if (L <= mid) {
ans = get_max(ans, self.max0(L, R, l, mid, rt << 1));
}
if R > mid {
ans = get_max(ans, self.max0(L, R, mid + 1, r, rt << 1 | 1));
}
return ans;
}
}

执行结果如下:


左神java代码

2022-12-10:给你一个由小写字母组成的字符串 s ,和一个整数 k 如果满足下述条件,则可以将字符串 t 视作是 理想字符串 : t 是字符串 s 的一个子序列。 t 中每两个 相邻 字母在字的更多相关文章

  1. [百度]数组A中任意两个相邻元素大小相差1,在其中查找某个数

    一.问题来源及描述 今天看了July的微博,发现了七月问题,有这个题,挺有意思的. 数组A中任意两个相邻元素大小相差1,现给定这样的数组A和目标整数t,找出t在数组A中的位置.如数组:[1,2,3,4 ...

  2. (笔试题)数组A中任意两个相邻元素大小相差1,在其中查找某个数。

    题目: 数组A中任意两个相邻元素大小相差1,现给定这样的数组A和目标整数t,找出t在数组A中的位置.如数组:[1,2,3,4,3,4,5,6,5],找到4在数组中的位置. 思路: 很明显,在数组中寻找 ...

  3. LeetCode 24. Swap Nodes in Pairs(交换链表中每两个相邻节点)

    题意:交换链表中每两个相邻节点,不能修改节点的val值. 分析:递归.如果以第三个结点为头结点的链表已经两两交换完毕(这一步递归实现---swapPairs(head -> next -> ...

  4. JZOJ 2022.02.10【提高组】模拟总结

    \(\text{简要题解}\) \(\text{GDOI2012}\) 的题 不得不说当年的题做起来真的很不爽 整体看起来就是数据结构+博弈论+宽搜+背包dp优化 考场上 \(T1\) 十分钟解决过了 ...

  5. 22.编写一个类A,该类创建的对象可以调用方法showA输出小写的英文字母表。然后再编写一个A类的子类B,子类B创建的对象不仅可以调用方法showA输出小写的英文字母表,而且可以调用子类新增的方法showB输出大写的英文字母表。最后编写主类C,在主类的main方法 中测试类A与类B。

    22.编写一个类A,该类创建的对象可以调用方法showA输出小写的英文字母表.然后再编写一个A类的子类B,子类B创建的对象不仅可以调用方法showA输出小写的英文字母表,而且可以调用子类新增的方法sh ...

  6. JS 从一个字符串中截取两个字符串之间的字符串

    /************************************************* 函数说明:从一个字符串中截取 两个字符串之间的字符串 参数说明:src_str 原串, start ...

  7. 黑马基础阶段测试题:创建一个存储字符串的集合list,向list中添加以下字符串:”C++”、”Java”、” Python”、”大数据与云计算”。遍历集合,将长度小于5的字符串从集合中删除,删除成功后,打印集合中的所有元素

    package com.swift; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; ...

  8. 给定一个字符串str,将str中连续两个字符为a的字符替换为b(一个或连续超过多个字符a则不替换)

    需求:给定一个字符串str,将str中连续两个字符为a的字符替换为b(一个或连续超过多个字符a则不替换) 如: a 不替换 b 不替换  ab 不替换 ba 不替换 aba 不替换  aab 替换为 ...

  9. C语言:根据形参c中指定的英文字母,按顺序打印出若干后继相邻字母,-主函数中放入一个带头节点的链表结构中,h指向链表的头节点。fun函数找出学生的最高分-使用插入排序法对字符串中的字符进行升序排序。-从文件中找到指定学号的学生数据,读入次学生数据,

    //根据形参c中指定的英文字母,按顺序打印出若干后继相邻字母,输出字母的大小与形参c一致,数量由形参d指定.例如:输入c为Y,d为4,则输出ZABC. #include <stdio.h> ...

  10. 2021.12.10 P2516 [HAOI2010]最长公共子序列(动态规划+滚动数组)

    2021.12.10 P2516 [HAOI2010]最长公共子序列(动态规划+滚动数组) https://www.luogu.com.cn/problem/P2516 题意: 给定字符串 \(S\) ...

随机推荐

  1. ios装包

    一.下载爱思助手 二.找到本机设备 注:如果未弹出允许.拒绝调试选项可尝试换根数据线解决 三.将对应包体文件拖入本机设备

  2. 在Mac上不常用但会用到的命令

    文章目录 1. chflags 2. rename 1. chflags chflags hidden filename 给文件添加隐藏属性 chflags nohidden filename 去掉文 ...

  3. (转)解决ubuntu下拼音输入法出错的问题

    一.如果仅在中文输入法下出现按键映射错位而英文输入下正常的情况,则在终端下输入以下命令即可: ibus-daemon -drx 二.如果拼音正常但打出来显示 "[Invalid UTF-8] ...

  4. Spring--AOP通知类型

    AOP通知类型 前置通知 通知类中的数据在原始数据的前面 后置通知 通知类中的数据在原始数据的后面 环绕通知 若是只是加一个注解: 我们需要这样做:加一个参数: 若是面对有返回值的方法,又有一点不同之 ...

  5. CF1286F Harry The Potter

    CF1286F Harry The Potter 首先答案上界为 \(n\),就是对每个点用一次操作 1. 那么我们现在的思维模式就是利用操作 2 来减少操作 1 的次数. 不难发现,如果操作 2 的 ...

  6. Prometheus Alertmanager生产配置趟过的坑总结

    简介 Alertmanager 处理由客户端应用程序(如 Prometheus server)发送的警报.它负责去重(deduplicating),分组(grouping),并将它们路由(routin ...

  7. SpringBoot——MVC原理

    更多内容,前往 IT-BLOG 一.SpringMVC自动配置 SpringMVC auto-configuration:SpringBoot 自动配置好了SpringMVC.以下是 SpringBo ...

  8. MySQL 索引的种类

    我们知道一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,所以查询语句的优化显然是重中之重. 一.平衡多路查 ...

  9. Moho Pro - Mac 上一款专业的二维动画制作软件,强大的功能让你尽情发挥创意

    Moho,以前被称为动画工作室专业版,是最好的质量的2D动画软件之一.这个程序是理想的专业人士寻找一个更有效的替代方法来创建动画,没有繁琐的详细逐帧处理.具有直观的界面和现成的人物和附加对象(卡通对象 ...

  10. Django笔记九之model查询filter、exclude、annotate、order_by

    在接下来四五篇笔记中,将介绍 model 查询方法的各个细节,为我们的查询操作提供各种便利. 本篇笔记将介绍惰性查找.filter.exclude.annotate等方法,目录如下: 惰性查找 fil ...