📌  相关文章
📜  具有不同相邻字符的最长子序列

📅  最后修改于: 2021-10-26 02:32:26             🧑  作者: Mango

给定字符串str 。任务是找到str的最长子序列,使得子序列中所有相邻的字符都不同。

例子:

方法一:贪心法
可以观察到,在给定字符串的最长子序列中,选择与先前选择的字符不相似的第一个字符,并且相邻字符不同。
这个想法是在遍历字符串时跟踪先前选择的字符,如果当前字符与前一个字符不同,则计算当前字符以找到最长的子序列。
下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to find the longest Subsequence
// with different adjacent character
int longestSubsequence(string s)
{
    // Length of the string s
    int n = s.length();
    int answer = 0;
 
    // Previously picked character
    char prev = '-';
 
    for (int i = 0; i < n; i++) {
        // If the current character is
        // different from the previous
        // then include this character
        // and update previous character
        if (prev != s[i]) {
            prev = s[i];
            answer++;
        }
    }
 
    return answer;
}
 
// Driver Code
int main()
{
    string str = "ababa";
 
    // Function call
    cout << longestSubsequence(str);
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
 
class GFG{
 
// Function to find the longest subsequence
// with different adjacent character
static int longestSubsequence(String s)
{
     
    // Length of the String s
    int n = s.length();
    int answer = 0;
 
    // Previously picked character
    char prev = '-';
 
    for(int i = 0; i < n; i++)
    {
 
       // If the current character is
       // different from the previous
       // then include this character
       // and update previous character
       if (prev != s.charAt(i))
       {
           prev = s.charAt(i);
           answer++;
       }
    }
 
    return answer;
}
 
// Driver Code
public static void main(String[] args)
{
    String str = "ababa";
 
    // Function call
    System.out.print(longestSubsequence(str));
}
}
 
// This code is contributed by sapnasingh4991


Python3
# Python3 program for the above approach
 
# Function to find the longest Subsequence
# with different adjacent character
def longestSubsequence(s):
 
    # Length of the string s
    n = len(s);
    answer = 0;
 
    # Previously picked character
    prev = '-';
 
    for i in range(0, n):
         
        # If the current character is
        # different from the previous
        # then include this character
        # and update previous character
        if (prev != s[i]):
            prev = s[i];
            answer += 1;
         
    return answer;
 
# Driver Code
str = "ababa";
 
# Function call
print(longestSubsequence(str));
 
# This code is contributed by Code_Mech


C#
// C# program for the above approach
using System;
 
class GFG{
 
// Function to find the longest subsequence
// with different adjacent character
static int longestSubsequence(String s)
{
     
    // Length of the String s
    int n = s.Length;
    int answer = 0;
 
    // Previously picked character
    char prev = '-';
 
    for(int i = 0; i < n; i++)
    {
        
       // If the current character is
       // different from the previous
       // then include this character
       // and update previous character
       if (prev != s[i])
       {
           prev = s[i];
           answer++;
       }
    }
    return answer;
}
 
// Driver Code
public static void Main(String[] args)
{
    String str = "ababa";
 
    // Function call
    Console.Write(longestSubsequence(str));
}
}
 
// This code is contributed by amal kumar choubey


Javascript


C++
// C++ program for the above approach
#include 
using namespace std;
 
// dp table
int dp[100005][27];
 
// A recursive function to find the
// update the dp[][] table
int calculate(int pos, int prev, string& s)
{
 
    // If we reach end of the string
    if (pos == s.length()) {
        return 0;
    }
 
    // If subproblem has been computed
    if (dp[pos][prev] != -1)
        return dp[pos][prev];
 
    // Initialise variable to find the
    // maximum length
    int val = 0;
 
    // Choose the current character
    if (s[pos] - 'a' + 1 != prev) {
        val = max(val,
                  1 + calculate(pos + 1,
                                s[pos] - 'a' + 1,
                                s));
    }
 
    // Omit the current character
    val = max(val, calculate(pos + 1, prev, s));
 
    // Return the store answer to the
    // current subproblem
    return dp[pos][prev] = val;
}
 
// Function to find the longest Subsequence
// with different adjacent character
int longestSubsequence(string s)
{
 
    // Length of the string s
    int n = s.length();
 
    // Initialise the memoisation table
    memset(dp, -1, sizeof(dp));
 
    // Return the final ans after every
    // recursive call
    return calculate(0, 0, s);
}
 
// Driver Code
int main()
{
    string str = "ababa";
 
    // Function call
    cout << longestSubsequence(str);
    return 0;
}


Java
// Java program for the above approach
class GFG{
 
// dp table
static int dp[][] = new int[100005][27];
 
// A recursive function to find the
// update the dp[][] table
static int calculate(int pos, int prev, String s)
{
 
    // If we reach end of the String
    if (pos == s.length())
    {
        return 0;
    }
 
    // If subproblem has been computed
    if (dp[pos][prev] != -1)
        return dp[pos][prev];
 
    // Initialise variable to find the
    // maximum length
    int val = 0;
 
    // Choose the current character
    if (s.charAt(pos) - 'a' + 1 != prev)
    {
        val = Math.max(val, 1 + calculate(pos + 1,
                                s.charAt(pos) - 'a' + 1,
                                s));
    }
 
    // Omit the current character
    val = Math.max(val, calculate(pos + 1, prev, s));
 
    // Return the store answer to the
    // current subproblem
    return dp[pos][prev] = val;
}
 
// Function to find the longest Subsequence
// with different adjacent character
static int longestSubsequence(String s)
{
 
    // Length of the String s
    int n = s.length();
 
    // Initialise the memoisation table
    for(int i = 0; i < 100005; i++)
    {
        for (int j = 0; j < 27; j++)
        {
            dp[i][j] = -1;
        }
    }
 
    // Return the final ans after every
    // recursive call
    return calculate(0, 0, s);
}
 
// Driver Code
public static void main(String[] args)
{
    String str = "ababa";
 
    // Function call
    System.out.print(longestSubsequence(str));
}
}
 
// This code is contributed by Rohit_ranjan


Python3
# Python3 program for the above approach
# dp table
dp = [[-1 for i in range(27)] for j in range(100005)];
 
# A recursive function to find the
# update the dp table
def calculate(pos, prev, s):
   
    # If we reach end of the String
    if (pos == len(s)):
        return 0;
 
    # If subproblem has been computed
    if (dp[pos][prev] != -1):
        return dp[pos][prev];
 
    # Initialise variable to find the
    # maximum length
    val = 0;
 
    # Choose the current character
    if (ord(s[pos]) - ord('a') + 1 != prev):
        val = max(val, 1 + calculate(pos + 1,
                                     ord(s[pos]) -
                                     ord('a') + 1, s));
 
    # Omit the current character
    val = max(val, calculate(pos + 1, prev, s));
 
    # Return the store answer to
    # the current subproblem
    dp[pos][prev] = val;
    return dp[pos][prev];
 
# Function to find the longest Subsequence
# with different adjacent character
def longestSubsequence(s):
   
    # Length of the String s
    n = len(s);
 
    # Return the final ans after every
    # recursive call
    return calculate(0, 0, s);
 
# Driver Code
if __name__ == '__main__':
    str = "ababa";
 
    # Function call
    print(longestSubsequence(str));
 
# This code is contributed by shikhasingrajput


C#
// C# program for the above approach
using System;
  
public class GFG{
  
// dp table
static int [,]dp = new int[100005,27];
  
// A recursive function to find the
// update the [,]dp table
static int calculate(int pos, int prev, String s)
{
     
    // If we reach end of the String
    if (pos == s.Length)
    {
        return 0;
    }
  
    // If subproblem has been computed
    if (dp[pos,prev] != -1)
        return dp[pos,prev];
  
    // Initialise variable to
    // find the maximum length
    int val = 0;
  
    // Choose the current character
    if (s[pos] - 'a' + 1 != prev)
    {
        val = Math.Max(val, 1 +
                       calculate(pos + 1,
                                 s[pos] - 'a' + 1,
                                 s));
    }
  
    // Omit the current character
    val = Math.Max(val, calculate(pos + 1, prev, s));
  
    // Return the store answer to the
    // current subproblem
    return dp[pos,prev] = val;
}
  
// Function to find the longest Subsequence
// with different adjacent character
static int longestSubsequence(String s)
{
  
    // Length of the String s
    int n = s.Length;
  
    // Initialise the memoisation table
    for(int i = 0; i < 100005; i++)
    {
        for (int j = 0; j < 27; j++)
        {
            dp[i,j] = -1;
        }
    }
  
    // Return the readonly ans after every
    // recursive call
    return calculate(0, 0, s);
}
  
// Driver Code
public static void Main(String[] args)
{
    String str = "ababa";
  
    // Function call
    Console.Write(longestSubsequence(str));
}
}
  
// This code is contributed by shikhasingrajput


Javascript


输出:
5

时间复杂度: O(N),其中 N 是给定字符串的长度。

方法二:动态规划

  1. 对于给定字符串str 中的每个字符,执行以下操作:
    • 为结果子序列选择字符串的当前字符,并为剩余的字符串重复查找结果子序列的下一个可能字符。
    • 省略当前字符并重复剩余字符串以查找结果子序列的下一个可能字符。
  2. 上述递归调用中的最大值将是具有不同相邻元素的最长子序列。
  3. 递推关系由下式给出:
Let dp[pos][prev] be the length of longest subsequence 
till index pos such that alphabet prev was picked previously.a dp[pos][prev] = max(1 + function(pos+1, s[pos] - 'a' + 1, s), 
                    function(pos+1, prev, s));

下面是上述方法的实现:

C++

// C++ program for the above approach
#include 
using namespace std;
 
// dp table
int dp[100005][27];
 
// A recursive function to find the
// update the dp[][] table
int calculate(int pos, int prev, string& s)
{
 
    // If we reach end of the string
    if (pos == s.length()) {
        return 0;
    }
 
    // If subproblem has been computed
    if (dp[pos][prev] != -1)
        return dp[pos][prev];
 
    // Initialise variable to find the
    // maximum length
    int val = 0;
 
    // Choose the current character
    if (s[pos] - 'a' + 1 != prev) {
        val = max(val,
                  1 + calculate(pos + 1,
                                s[pos] - 'a' + 1,
                                s));
    }
 
    // Omit the current character
    val = max(val, calculate(pos + 1, prev, s));
 
    // Return the store answer to the
    // current subproblem
    return dp[pos][prev] = val;
}
 
// Function to find the longest Subsequence
// with different adjacent character
int longestSubsequence(string s)
{
 
    // Length of the string s
    int n = s.length();
 
    // Initialise the memoisation table
    memset(dp, -1, sizeof(dp));
 
    // Return the final ans after every
    // recursive call
    return calculate(0, 0, s);
}
 
// Driver Code
int main()
{
    string str = "ababa";
 
    // Function call
    cout << longestSubsequence(str);
    return 0;
}

Java

// Java program for the above approach
class GFG{
 
// dp table
static int dp[][] = new int[100005][27];
 
// A recursive function to find the
// update the dp[][] table
static int calculate(int pos, int prev, String s)
{
 
    // If we reach end of the String
    if (pos == s.length())
    {
        return 0;
    }
 
    // If subproblem has been computed
    if (dp[pos][prev] != -1)
        return dp[pos][prev];
 
    // Initialise variable to find the
    // maximum length
    int val = 0;
 
    // Choose the current character
    if (s.charAt(pos) - 'a' + 1 != prev)
    {
        val = Math.max(val, 1 + calculate(pos + 1,
                                s.charAt(pos) - 'a' + 1,
                                s));
    }
 
    // Omit the current character
    val = Math.max(val, calculate(pos + 1, prev, s));
 
    // Return the store answer to the
    // current subproblem
    return dp[pos][prev] = val;
}
 
// Function to find the longest Subsequence
// with different adjacent character
static int longestSubsequence(String s)
{
 
    // Length of the String s
    int n = s.length();
 
    // Initialise the memoisation table
    for(int i = 0; i < 100005; i++)
    {
        for (int j = 0; j < 27; j++)
        {
            dp[i][j] = -1;
        }
    }
 
    // Return the final ans after every
    // recursive call
    return calculate(0, 0, s);
}
 
// Driver Code
public static void main(String[] args)
{
    String str = "ababa";
 
    // Function call
    System.out.print(longestSubsequence(str));
}
}
 
// This code is contributed by Rohit_ranjan

蟒蛇3

# Python3 program for the above approach
# dp table
dp = [[-1 for i in range(27)] for j in range(100005)];
 
# A recursive function to find the
# update the dp table
def calculate(pos, prev, s):
   
    # If we reach end of the String
    if (pos == len(s)):
        return 0;
 
    # If subproblem has been computed
    if (dp[pos][prev] != -1):
        return dp[pos][prev];
 
    # Initialise variable to find the
    # maximum length
    val = 0;
 
    # Choose the current character
    if (ord(s[pos]) - ord('a') + 1 != prev):
        val = max(val, 1 + calculate(pos + 1,
                                     ord(s[pos]) -
                                     ord('a') + 1, s));
 
    # Omit the current character
    val = max(val, calculate(pos + 1, prev, s));
 
    # Return the store answer to
    # the current subproblem
    dp[pos][prev] = val;
    return dp[pos][prev];
 
# Function to find the longest Subsequence
# with different adjacent character
def longestSubsequence(s):
   
    # Length of the String s
    n = len(s);
 
    # Return the final ans after every
    # recursive call
    return calculate(0, 0, s);
 
# Driver Code
if __name__ == '__main__':
    str = "ababa";
 
    # Function call
    print(longestSubsequence(str));
 
# This code is contributed by shikhasingrajput

C#

// C# program for the above approach
using System;
  
public class GFG{
  
// dp table
static int [,]dp = new int[100005,27];
  
// A recursive function to find the
// update the [,]dp table
static int calculate(int pos, int prev, String s)
{
     
    // If we reach end of the String
    if (pos == s.Length)
    {
        return 0;
    }
  
    // If subproblem has been computed
    if (dp[pos,prev] != -1)
        return dp[pos,prev];
  
    // Initialise variable to
    // find the maximum length
    int val = 0;
  
    // Choose the current character
    if (s[pos] - 'a' + 1 != prev)
    {
        val = Math.Max(val, 1 +
                       calculate(pos + 1,
                                 s[pos] - 'a' + 1,
                                 s));
    }
  
    // Omit the current character
    val = Math.Max(val, calculate(pos + 1, prev, s));
  
    // Return the store answer to the
    // current subproblem
    return dp[pos,prev] = val;
}
  
// Function to find the longest Subsequence
// with different adjacent character
static int longestSubsequence(String s)
{
  
    // Length of the String s
    int n = s.Length;
  
    // Initialise the memoisation table
    for(int i = 0; i < 100005; i++)
    {
        for (int j = 0; j < 27; j++)
        {
            dp[i,j] = -1;
        }
    }
  
    // Return the readonly ans after every
    // recursive call
    return calculate(0, 0, s);
}
  
// Driver Code
public static void Main(String[] args)
{
    String str = "ababa";
  
    // Function call
    Console.Write(longestSubsequence(str));
}
}
  
// This code is contributed by shikhasingrajput

Javascript


输出:
5

时间复杂度: O(N),其中 N 是给定字符串的长度。
辅助空间: O(26*N) 其中 N 是给定字符串的长度。