📜  差异最大为K的最长子序列

📅  最后修改于: 2021-04-22 01:27:25             🧑  作者: Mango

给定长度为N且整数为K的字符串S ,任务是找到最长子序列的长度,以使子序列中相邻字符的ASCII值之差不超过K。

例子:

Input: N = 7, K = 2, S = "afcbedg"
Output: 4
Explantion:
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 ,其大小等于字符串的长度。
  • 创建大小为26的0的支持数组max_length
  • 迭代由字符和用于每个字符的字符串的字符确定上限和下限。
  • 在上下限范围内迭代嵌套循环。
  • 用当前dp索引和当前max_length索引+1之间的最大值填充dp数组。
  • 用当前dp索引和当前max_length索引之间的最大值填充max_length数组。
  • 最长子序列长度是dp数组中的最大值。
  • 让我们考虑一个例子:
  • 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


输出:
7