给定一个长度为N的字符串S和一个整数K ,任务是找到最长子序列的长度,使得子序列中相邻字符的 ASCII 值之间的差异不超过 K。
例子:
Input: N = 7, K = 2, S = "afcbedg"
Output: 4
Explanation:
Longest special sequence present
in "afcbedg" is a, c, b, d.
It is special because |a - c| <= 2,
|c - b| <= 2 and | b-d| <= 2
Input: N = 13, K = 3, S = "geeksforgeeks"
Output: 7
朴素的方法:暴力解决方案是生成各种长度的所有可能子序列并计算有效子序列的最大长度。时间复杂度将是指数级的。
高效的方法:一种有效的方法是使用动态规划的概念
- 创建一个大小等于字符串长度的 0 数组dp 。
- 创建一个支持数组max_length,其中 0 的大小为 26。
- 迭代由字符和用于每个字符的字符串的字符确定上限和下限。
- 在上下限范围内迭代嵌套循环。
- 用当前dp索引和当前 max_length 索引+1 之间的最大值填充 dp 数组。
- 用当前dp索引和当前 max_length 索引之间的最大值填充 max_length 数组。
- 最长子序列长度是dp数组中的最大值。
- 让我们考虑一个例子:
input string s is “afcbedg” and k is 2
- for 1st iteration value of i is ‘a’ and range of j is (0, 2)
and current dp = [1, 0, 0, 0, 0, 0, 0] - for 2nd iteration value of i is ‘f’ and range of j is (3, 7)
and current dp = [1, 1, 0, 0, 0, 0, 0] - for 3rd iteration value of i is ‘c’ and range of j is (0, 4)
and current dp = [1, 1, 2, 0, 0, 0, 0] - for 4th iteration value of i is ‘b’ and range of j is (0, 3)
and current dp = [1, 1, 2, 3, 0, 0, 0] - for 5th iteration value of i is ‘e’ and range of j is (2, 6)
and current dp = [1, 1, 2, 3, 3, 0, 0] - for 6th iteration value of i is ‘d’ and range of j is (1, 5)
and current dp = [1, 1, 2, 3, 3, 4, 0] - for 7th iteration value of i is ‘g’ and range of j is (4, 8)
and current dp = [1, 1, 2, 3, 3, 4, 4]
longest length is the maximum value in dp so maximum length is 4
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find
// the longest Special Sequence
int longest_subseq(int n, int k, string s)
{
// Creating a list with
// all 0's of size
// equal to the length of string
vector dp(n, 0);
// Supporting list with
// all 0's of size 26 since
// the given string consists
// of only lower case alphabets
int max_length[26] = {0};
for (int i = 0; i < n; i++)
{
// Converting the ascii value to
// list indices
int curr = s[i] - 'a';
// Determining the lower bound
int lower = max(0, curr - k);
// Determining the upper bound
int upper = min(25, curr + k);
// Filling the dp array with values
for (int j = lower; j < upper + 1; j++)
{
dp[i] = max(dp[i], max_length[j] + 1);
}
//Filling the max_length array with max
//length of subsequence till now
max_length[curr] = max(dp[i], max_length[curr]);
}
int ans = 0;
for(int i:dp) ans = max(i, ans);
// return the max length of subsequence
return ans;
}
// Driver Code
int main()
{
string s = "geeksforgeeks";
int n = s.size();
int k = 3;
cout << (longest_subseq(n, k, s));
return 0;
}
// This code is contributed by Mohit Kumar
Java
// Java program for the above approach
class GFG
{
// Function to find
// the longest Special Sequence
static int longest_subseq(int n, int k, String s)
{
// Creating a list with
// all 0's of size
// equal to the length of String
int []dp = new int[n];
// Supporting list with
// all 0's of size 26 since
// the given String consists
// of only lower case alphabets
int []max_length = new int[26];
for (int i = 0; i < n; i++)
{
// Converting the ascii value to
// list indices
int curr = s.charAt(i) - 'a';
// Determining the lower bound
int lower = Math.max(0, curr - k);
// Determining the upper bound
int upper = Math.min(25, curr + k);
// Filling the dp array with values
for (int j = lower; j < upper + 1; j++)
{
dp[i] = Math.max(dp[i], max_length[j] + 1);
}
// Filling the max_length array with max
// length of subsequence till now
max_length[curr] = Math.max(dp[i], max_length[curr]);
}
int ans = 0;
for(int i:dp) ans = Math.max(i, ans);
// return the max length of subsequence
return ans;
}
// Driver Code
public static void main(String[] args)
{
String s = "geeksforgeeks";
int n = s.length();
int k = 3;
System.out.print(longest_subseq(n, k, s));
}
}
// This code is contributed by 29AjayKumar
Python3
# Function to find
# the longest Special Sequence
def longest_subseq(n, k, s):
# Creating a list with
# all 0's of size
# equal to the length of string
dp = [0] * n
# Supporting list with
# all 0's of size 26 since
# the given string consists
# of only lower case alphabets
max_length = [0] * 26
for i in range(n):
# Converting the ascii value to
# list indices
curr = ord(s[i]) - ord('a')
# Determining the lower bound
lower = max(0, curr - k)
# Determining the upper bound
upper = min(25, curr + k)
# Filling the dp array with values
for j in range(lower, upper + 1):
dp[i] = max(dp[i], max_length[j]+1)
# Filling the max_length array with max
# length of subsequence till now
max_length[curr] = max(dp[i], max_length[curr])
# return the max length of subsequence
return max(dp)
# driver code
def main():
s = "geeksforgeeks"
n = len(s)
k = 3
print(longest_subseq(n, k, s))
main()
C#
// C# program for the above approach
using System;
class GFG
{
// Function to find
// the longest Special Sequence
static int longest_subseq(int n, int k, String s)
{
// Creating a list with
// all 0's of size
// equal to the length of String
int []dp = new int[n];
// Supporting list with
// all 0's of size 26 since
// the given String consists
// of only lower case alphabets
int []max_length = new int[26];
for (int i = 0; i < n; i++)
{
// Converting the ascii value to
// list indices
int curr = s[i] - 'a';
// Determining the lower bound
int lower = Math.Max(0, curr - k);
// Determining the upper bound
int upper = Math.Min(25, curr + k);
// Filling the dp array with values
for (int j = lower; j < upper + 1; j++)
{
dp[i] = Math.Max(dp[i], max_length[j] + 1);
}
// Filling the max_length array with max
// length of subsequence till now
max_length[curr] = Math.Max(dp[i], max_length[curr]);
}
int ans = 0;
foreach(int i in dp) ans = Math.Max(i, ans);
// return the max length of subsequence
return ans;
}
// Driver Code
public static void Main(String[] args)
{
String s = "geeksforgeeks";
int n = s.Length;
int k = 3;
Console.Write(longest_subseq(n, k, s));
}
}
// This code is contributed by Rajput-Ji
Javascript
输出:
7
时间复杂度: O(N)
辅助空间: O(N)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。