📜  最短不常见子序列

📅  最后修改于: 2021-09-22 09:40:45             🧑  作者: Mango

给定两个字符串S 和 T,找出 S 中不是 T 中的子序列的最短子序列的长度。如果没有这样的子序列,则返回 -1。子序列是以相同的相对顺序出现的序列,但不一定是连续的。长度为 n 的字符串有 2^n 个不同的可能子序列。
长度为 m 的字符串 S (1 <= m <= 1000)
长度为 n 的字符串 T (1 <= n <= 1000)
例子:

Input : S = “babab” T = “babba”
Output : 3
The subsequence “aab” of length 3 is 
present in S but not in T.

Input :  S = “abb” T = “abab”
Output : -1
There is no subsequence that is present 
in S but not in T.


蛮力法
一个简单的方法是生成字符串S 的所有子序列,并为每个子序列检查它是否存在于字符串T 中。考虑示例 2,其中 S = “abb”,
它的子序列是“”、“a”、“b”、“ab”、“bb”、“abb”,每个都出现在“abab”中。该解决方案的时间复杂度将呈指数级增长。
高效(动态规划)
1.最优子结构:分别考虑长度为 m 和 n 的两个字符串S 和 T,让查找最短不常见子序列的函数为shortestSeq (char *S, char *T)。对于 S 中的每个字符,如果它不存在于 T 中,那么该字符就是答案本身。
否则,如果它在索引 k 处找到,那么我们可以选择将它包含在最短的不常见子序列中或不包含它。

If it is included answer = 1 + ShortestSeq( S + 1, T + k + 1) 
If not included answer =  ShortestSeq( S + 1, T) 
The minimum of the two is the answer.

因此,我们可以看到这个问题具有最优子结构性质,因为它可以通过使用子问题的解来解决。
2.重叠子问题
以下是上述问题的简单递归实现。

C++
// A simple recursive C++ program to find shortest
// uncommon subsequence.
#include
using namespace std;
 
#define MAX 1005
 
/* A recursive function to find the length of
   shortest uncommon subsequence*/
int shortestSeq(char *S, char *T, int m, int n)
{
    // S string is empty
    if (m == 0)
        return MAX;
 
    // T string is empty
    if (n <= 0)
        return 1;
 
    // Loop to search for current character
    int k;
    for (k=0; k < n; k++)
        if (T[k] == S[0])
            break;
 
    // char not found in T
    if (k == n)
        return 1;
 
    // Return minimum of following two
    // Not including current char in answer
    // Including current char
    return min(shortestSeq(S+1, T, m-1, n),
            1 + shortestSeq(S+1, T+k+1, m-1, n-k-1));
}
 
// Driver program to test the above function
int main()
{
    char S[] = "babab";
    char T[] = "babba";
    int m = strlen(S), n = strlen(T);
    int ans = shortestSeq(S, T, m, n);
    if (ans >= MAX)
       ans = -1;
    cout << "Length of shortest subsequence is: "
         << ans << endl;
    return 0;
}


Java
// A simple recursive Java program to find shortest
// uncommon subsequence.
import java.util.*;
 
class GFG
{
 
static final int MAX = 1005;
 
/* A recursive function to find the length of
shortest uncommon subsequence*/
static int shortestSeq(char []S, char []T, int m, int n)
{
    // S String is empty
    if (m == 0)
        return MAX;
 
    // T String is empty
    if (n <= 0)
        return 1;
 
    // Loop to search for current character
    int k;
    for (k = 0; k < n; k++)
        if (T[k] == S[0])
            break;
 
    // char not found in T
    if (k == n)
        return 1;
 
    // Return minimum of following two
    // Not including current char in answer
    // Including current char
    return Math.min(shortestSeq(Arrays.copyOfRange(S, 1, S.length), T, m - 1, n),
                    1 + shortestSeq(Arrays.copyOfRange(S, 1, S.length),
                    Arrays.copyOfRange(T, k + 1, T.length), m - 1, n - k - 1));
}
 
// Driver code
public static void main(String[] args)
{
    char S[] = "babab".toCharArray();
    char T[] = "babba".toCharArray();
    int m = S.length, n = T.length;
    int ans = shortestSeq(S, T, m, n);
    if (ans >= MAX)
    ans = -1;
    System.out.print("Length of shortest subsequence is: "
        + ans +"\n");
}
}
 
// This code is contributed by Rajput-Ji


Python3
# A simple recursive Python
# program to find shortest
# uncommon subsequence.
MAX = 1005
 
# A recursive function to
# find the length of shortest
# uncommon subsequence
def shortestSeq(S, T, m, n):
 
    # S String is empty
    if m == 0:
        return MAX
 
    # T String is empty
    if(n <= 0):
        return 1
 
    # Loop to search for
    # current character
    for k in range(n):
        if(T[k] == S[0]):
            break
 
    # char not found in T
    if(k == n):
        return 1
 
    # Return minimum of following
    # two Not including current
    # char in answer Including
    # current char
    return min(shortestSeq(S[1 : ], T, m - 1, n),
               1 + shortestSeq((S[1 : ]), T[k + 1 : ],
                                m - 1, n - k - 1))
 
# Driver code
S = "babab"
T = "babba"
 
m = len(S)
n = len(T)
ans = shortestSeq(S, T, m, n)
if(ans >= MAX):
    ans =- 1
print("Length of shortest subsequence is:", ans)
 
# This code is contributed by avanitrachhadiya2155


C#
// A simple recursive C# program to find shortest
// uncommon subsequence.
using System;
 
class GFG
{
 
static readonly int MAX = 1005;
 
/* A recursive function to find the length of
shortest uncommon subsequence*/
static int shortestSeq(char []S, char []T, int m, int n)
{
    // S String is empty
    if (m == 0)
        return MAX;
 
    // T String is empty
    if (n <= 0)
        return 1;
 
    // Loop to search for current character
    int k;
    for (k = 0; k < n; k++)
        if (T[k] == S[0])
            break;
 
    // char not found in T
    if (k == n)
        return 1;
 
    // Return minimum of following two
    // Not including current char in answer
    // Including current char
    char []St1 = new Char[S.Length - 1];
    Array.Copy(S, 1, St1, 0, S.Length - 1);
    char []St2 = new Char[S.Length - 1];
    Array.Copy(S, 1, St2, 0, S.Length - 1);
    char []Tt1 = new Char[T.Length - (k + 1)];
    Array.Copy(T, k + 1, Tt1, 0, T.Length - (k + 1));
    return Math.Min(shortestSeq(St1, T, m - 1, n),
                    1 + shortestSeq(St2, Tt1, m - 1, n - k - 1));
}
 
// Driver code
public static void Main(String[] args)
{
    char []S = "babab".ToCharArray();
    char []T = "babba".ToCharArray();
    int m = S.Length, n = T.Length;
    int ans = shortestSeq(S, T, m, n);
    if (ans >= MAX)
    ans = -1;
    Console.Write("Length of shortest subsequence is: "
        + ans +"\n");
}
}
 
// This code is contributed by Rajput-Ji


C++
// A dynamic programming based C++ program
// to find shortest uncommon subsequence.
#include
using namespace std;
 
#define MAX 1005
 
// Returns length of shortest common subsequence
int shortestSeq(char *S, char *T)
{
    int m = strlen(S), n = strlen(T);
 
    // declaring 2D array of m + 1 rows and
    // n + 1 columns dynamically
    int dp[m+1][n+1];
 
    // T string is empty
    for (int i = 0; i <= m; i++)
        dp[i][0] = 1;
 
    // S string is empty
    for (int i = 0; i <= n; i++)
        dp[0][i] = MAX;
 
    for (int i = 1; i <= m; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            char ch = S[i-1];
            int k;
            for (k = j-1; k >= 0; k--)
                if (T[k] == ch)
                    break;
 
            // char not present in T
            if (k == -1)
                dp[i][j] = 1;
            else
               dp[i][j] = min(dp[i-1][j], dp[i-1][k] + 1);
        }
    }
 
    int ans = dp[m][n];
    if (ans >= MAX)
        ans = -1;
 
    return ans;
}
 
// Driver program to test the above function
int main()
{
    char S[] = "babab";
    char T[] = "babba";
    int m = strlen(S), n = strlen(T);
    cout << "Length of shortest subsequence is : "
         << shortestSeq(S, T) << endl;
}


Java
// A dynamic programming based Java program
// to find shortest uncommon subsequence.
class GFG
{
 
    static final int MAX = 1005;
 
    // Returns length of shortest common subsequence
    static int shortestSeq(char[] S, char[] T)
    {
        int m = S.length, n = T.length;
 
        // declaring 2D array of m + 1 rows and
        // n + 1 columns dynamically
        int dp[][] = new int[m + 1][n + 1];
 
        // T string is empty
        for (int i = 0; i <= m; i++)
        {
            dp[i][0] = 1;
        }
 
        // S string is empty
        for (int i = 0; i <= n; i++)
        {
            dp[0][i] = MAX;
        }
 
        for (int i = 1; i <= m; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                char ch = S[i - 1];
                int k;
                for (k = j - 1; k >= 0; k--)
                {
                    if (T[k] == ch)
                    {
                        break;
                    }
                }
 
                // char not present in T
                if (k == -1)
                {
                    dp[i][j] = 1;
                }
                else
                {
                    dp[i][j] = Math.min(dp[i - 1][j],
                                    dp[i - 1][k] + 1);
                }
            }
        }
 
        int ans = dp[m][n];
        if (ans >= MAX)
        {
            ans = -1;
        }
        return ans;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        char S[] = "babab".toCharArray();
        char T[] = "babba".toCharArray();
        int m = S.length, n = T.length;
        System.out.println("Length of shortest" +
                            "subsequence is : " +
                            shortestSeq(S, T));
    }
}
 
// This code is contributed by 29AjayKumar


Python3
# A dynamic programming based Python program
# to find shortest uncommon subsequence.
MAX = 1005
 
# Returns length of shortest common subsequence
def shortestSeq(S: list, T: list):
    m = len(S)
    n = len(T)
 
    # declaring 2D array of m + 1 rows and
    # n + 1 columns dynamically
    dp = [[0 for i in range(n + 1)]
             for j in range(m + 1)]
 
    # T string is empty
    for i in range(m + 1):
        dp[i][0] = 1
 
    # S string is empty
    for i in range(n + 1):
        dp[0][i] = MAX
 
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            ch = S[i - 1]
            k = j - 1
            while k >= 0:
                if T[k] == ch:
                    break
                k -= 1
 
            # char not present in T
            if k == -1:
                dp[i][j] = 1
            else:
                dp[i][j] = min(dp[i - 1][j],
                               dp[i - 1][k] + 1)
 
    ans = dp[m][n]
    if ans >= MAX:
        ans = -1
 
    return ans
 
# Driver Code
if __name__ == "__main__":
    S = "babab"
    T = "babba"
 
    print("Length of shortest subsequence is:",
                             shortestSeq(S, T))
 
# This code is contributed by
# sanjeev2552


C#
// A dynamic programming based C# program
// to find shortest uncommon subsequence.
using System;
 
class GFG
{
 
    static readonly int MAX = 1005;
 
    // Returns length of shortest common subsequence
    static int shortestSeq(char[] S, char[] T)
    {
        int m = S.Length, n = T.Length;
 
        // declaring 2D array of m + 1 rows and
        // n + 1 columns dynamically
        int [,]dp = new int[m + 1, n + 1];
 
        // T string is empty
        for (int i = 0; i <= m; i++)
        {
            dp[i, 0] = 1;
        }
 
        // S string is empty
        for (int i = 0; i <= n; i++)
        {
            dp[0, i] = MAX;
        }
 
        for (int i = 1; i <= m; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                char ch = S[i - 1];
                int k;
                for (k = j - 1; k >= 0; k--)
                {
                    if (T[k] == ch)
                    {
                        break;
                    }
                }
 
                // char not present in T
                if (k == -1)
                {
                    dp[i, j] = 1;
                }
                else
                {
                    dp[i, j] = Math.Min(dp[i - 1, j],
                                    dp[i - 1, k] + 1);
                }
            }
        }
 
        int ans = dp[m, n];
        if (ans >= MAX)
        {
            ans = -1;
        }
        return ans;
    }
 
    // Driver code
    public static void Main(String[] args)
    {
        char []S = "babab".ToCharArray();
        char []T = "babba".ToCharArray();
        int m = S.Length, n = T.Length;
        Console.WriteLine("Length of shortest" +
                            "subsequence is : " +
                            shortestSeq(S, T));
    }
}
 
// This code contributed by Rajput-Ji


PHP
= 0; $k--)
                if ($T[$k] == $ch)
                    break;
 
            // char not present in T
            if ($k == -1)
                $dp[$i][$j] = 1;
            else
            $dp[$i][$j] = min($dp[$i - 1][$j], 
                              $dp[$i - 1][$k] + 1);
        }
    }
 
    $ans = $dp[$m][$n];
    if ($ans >= $GLOBALS['MAX'])
        $ans = -1;
 
    return $ans;
}
 
// Driver Code
$S = "babab";
$T = "babba";
$m = strlen($S);
$n = strlen($T);
echo "Length of shortest subsequence is : ",
                        shortestSeq($S, $T);
 
// This code is contributed by Ryuga
?>


输出:

Length of shortest subsequence is : 3

如果我们画出完整的递归树,那么我们可以看到有很多子问题被一次又一次地解决了。所以这个问题具有重叠子结构的性质,并且可以通过使用 Memoization 或 Tabulation 来避免相同子问题的重新计算。下面是问题的一个列表实现。

最长不常见子序列

C++

// A dynamic programming based C++ program
// to find shortest uncommon subsequence.
#include
using namespace std;
 
#define MAX 1005
 
// Returns length of shortest common subsequence
int shortestSeq(char *S, char *T)
{
    int m = strlen(S), n = strlen(T);
 
    // declaring 2D array of m + 1 rows and
    // n + 1 columns dynamically
    int dp[m+1][n+1];
 
    // T string is empty
    for (int i = 0; i <= m; i++)
        dp[i][0] = 1;
 
    // S string is empty
    for (int i = 0; i <= n; i++)
        dp[0][i] = MAX;
 
    for (int i = 1; i <= m; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            char ch = S[i-1];
            int k;
            for (k = j-1; k >= 0; k--)
                if (T[k] == ch)
                    break;
 
            // char not present in T
            if (k == -1)
                dp[i][j] = 1;
            else
               dp[i][j] = min(dp[i-1][j], dp[i-1][k] + 1);
        }
    }
 
    int ans = dp[m][n];
    if (ans >= MAX)
        ans = -1;
 
    return ans;
}
 
// Driver program to test the above function
int main()
{
    char S[] = "babab";
    char T[] = "babba";
    int m = strlen(S), n = strlen(T);
    cout << "Length of shortest subsequence is : "
         << shortestSeq(S, T) << endl;
}

Java

// A dynamic programming based Java program
// to find shortest uncommon subsequence.
class GFG
{
 
    static final int MAX = 1005;
 
    // Returns length of shortest common subsequence
    static int shortestSeq(char[] S, char[] T)
    {
        int m = S.length, n = T.length;
 
        // declaring 2D array of m + 1 rows and
        // n + 1 columns dynamically
        int dp[][] = new int[m + 1][n + 1];
 
        // T string is empty
        for (int i = 0; i <= m; i++)
        {
            dp[i][0] = 1;
        }
 
        // S string is empty
        for (int i = 0; i <= n; i++)
        {
            dp[0][i] = MAX;
        }
 
        for (int i = 1; i <= m; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                char ch = S[i - 1];
                int k;
                for (k = j - 1; k >= 0; k--)
                {
                    if (T[k] == ch)
                    {
                        break;
                    }
                }
 
                // char not present in T
                if (k == -1)
                {
                    dp[i][j] = 1;
                }
                else
                {
                    dp[i][j] = Math.min(dp[i - 1][j],
                                    dp[i - 1][k] + 1);
                }
            }
        }
 
        int ans = dp[m][n];
        if (ans >= MAX)
        {
            ans = -1;
        }
        return ans;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        char S[] = "babab".toCharArray();
        char T[] = "babba".toCharArray();
        int m = S.length, n = T.length;
        System.out.println("Length of shortest" +
                            "subsequence is : " +
                            shortestSeq(S, T));
    }
}
 
// This code is contributed by 29AjayKumar

蟒蛇3

# A dynamic programming based Python program
# to find shortest uncommon subsequence.
MAX = 1005
 
# Returns length of shortest common subsequence
def shortestSeq(S: list, T: list):
    m = len(S)
    n = len(T)
 
    # declaring 2D array of m + 1 rows and
    # n + 1 columns dynamically
    dp = [[0 for i in range(n + 1)]
             for j in range(m + 1)]
 
    # T string is empty
    for i in range(m + 1):
        dp[i][0] = 1
 
    # S string is empty
    for i in range(n + 1):
        dp[0][i] = MAX
 
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            ch = S[i - 1]
            k = j - 1
            while k >= 0:
                if T[k] == ch:
                    break
                k -= 1
 
            # char not present in T
            if k == -1:
                dp[i][j] = 1
            else:
                dp[i][j] = min(dp[i - 1][j],
                               dp[i - 1][k] + 1)
 
    ans = dp[m][n]
    if ans >= MAX:
        ans = -1
 
    return ans
 
# Driver Code
if __name__ == "__main__":
    S = "babab"
    T = "babba"
 
    print("Length of shortest subsequence is:",
                             shortestSeq(S, T))
 
# This code is contributed by
# sanjeev2552

C#

// A dynamic programming based C# program
// to find shortest uncommon subsequence.
using System;
 
class GFG
{
 
    static readonly int MAX = 1005;
 
    // Returns length of shortest common subsequence
    static int shortestSeq(char[] S, char[] T)
    {
        int m = S.Length, n = T.Length;
 
        // declaring 2D array of m + 1 rows and
        // n + 1 columns dynamically
        int [,]dp = new int[m + 1, n + 1];
 
        // T string is empty
        for (int i = 0; i <= m; i++)
        {
            dp[i, 0] = 1;
        }
 
        // S string is empty
        for (int i = 0; i <= n; i++)
        {
            dp[0, i] = MAX;
        }
 
        for (int i = 1; i <= m; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                char ch = S[i - 1];
                int k;
                for (k = j - 1; k >= 0; k--)
                {
                    if (T[k] == ch)
                    {
                        break;
                    }
                }
 
                // char not present in T
                if (k == -1)
                {
                    dp[i, j] = 1;
                }
                else
                {
                    dp[i, j] = Math.Min(dp[i - 1, j],
                                    dp[i - 1, k] + 1);
                }
            }
        }
 
        int ans = dp[m, n];
        if (ans >= MAX)
        {
            ans = -1;
        }
        return ans;
    }
 
    // Driver code
    public static void Main(String[] args)
    {
        char []S = "babab".ToCharArray();
        char []T = "babba".ToCharArray();
        int m = S.Length, n = T.Length;
        Console.WriteLine("Length of shortest" +
                            "subsequence is : " +
                            shortestSeq(S, T));
    }
}
 
// This code contributed by Rajput-Ji

PHP

= 0; $k--)
                if ($T[$k] == $ch)
                    break;
 
            // char not present in T
            if ($k == -1)
                $dp[$i][$j] = 1;
            else
            $dp[$i][$j] = min($dp[$i - 1][$j], 
                              $dp[$i - 1][$k] + 1);
        }
    }
 
    $ans = $dp[$m][$n];
    if ($ans >= $GLOBALS['MAX'])
        $ans = -1;
 
    return $ans;
}
 
// Driver Code
$S = "babab";
$T = "babba";
$m = strlen($S);
$n = strlen($T);
echo "Length of shortest subsequence is : ",
                        shortestSeq($S, $T);
 
// This code is contributed by Ryuga
?>

输出:

Length of shortest subsequence is : 3


如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程