📌  相关文章
📜  检查字符串是否可以通过另一个字符串的追加子序列来获得

📅  最后修改于: 2021-04-29 12:18:56             🧑  作者: Mango

给定两个分别具有长度NM的字符串str1str2 ,任务是检查是否可以通过多次附加str1的子序列来形成str2 。如果可能,请打印所需的最少附加操作数。否则,打印-1

例子:

方法:该想法是基于以下观察结果使用散列的概念:

  • 考虑字符串str1 =“ abb”str2 =“ aba” 。查找字符str2 [0]str1中的位置,该字符的索引大于或等于0,str1的索引0
  • 同样,在str1中找到str2 [1] ,使其索引大于或等于1,str1的索引1
  • 然后,在str1中找到str2 [2] ,使其索引大于或等于2 (不存在)。
  • 因此,再次从索引0开始,在str1中找到具有大于或等于索引0的索引,即str1的索引0str2 [2]
  • 因此,可以附加两个子序列“ ab”“ a”以形成“ aba”

请按照以下步骤解决问题:

  • 初始化长度为26的向量vec []的数组。
  • 将所有具有字符‘a’的索引str1推入vec [0] 。同样,在vec [1]中推送所有字符‘b’的索引。对从‘a’‘z’的每个字符执行此操作。
  • 1初始化一个变量结果,用0初始化position,以存储最小操作数和str1的当前位置。
  • [0,M]范围内遍历字符串str2 ,并对每个字符执行以下操作:
    • 如果VEC [STR2 [I] – ‘A’]是空的,则字符STR2 [i]是不存在于STR1。因此,答案是不可能的。因此,打印-1
    • 否则,在vec [str2 [i] –’a’]中找到位置的下限。设为p 。如果p等于vec [str2 [i] –’a’]的大小,则将结果加1 ,将i1,因为尚未找到字符str2 [i]的答案并将位置设置为0
    • 否则,将位置设置为(vec [p] + 1)
  • 遍历后,将结果打印为所需的最少操作。

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
 
using namespace std;
 
// Function to find minimum operations
// required to form str2 by adding
// subsequences of str1
void find(string str1, string str2)
{
 
    // Initialize vector of length 26
    vector vec1[26];
 
    // Push indices of characters of str1
    for (int i = 0; i < str1.size(); i++)
        vec1[str1[i] - 'a'].push_back(i);
 
    // Initialize the result & position
    int result = 1, position = 0;
 
    // Traverse the string str2
    for (int i = 0; i < str2.size(); i++)
    {
 
        char c = str2[i];
 
        // Return if no answer exist
        if (vec1.empty())
        {
            result = -1;
            break;
        }
 
        // Pointer of vec1[c-'a']
        vector& vec2 = vec1;
 
        // Lower bound of position
        int p = lower_bound(vec2.begin(),
                            vec2.end(),
                            position)
                - vec2.begin();
 
        // If no index found
        if (p == vec2.size())
        {
            // Increment result
            result++;
            i--;
            position = 0;
            continue;
        }
 
        // Update the position
        else {
            position = vec2[p] + 1;
        }
    }
 
    // Print the result
    cout << result << '\n';
}
 
// Driver Code
int main()
{
    // Given string str1 & str2
    string str1 = "abb", str2 = "ababbbbb";
 
    // Function Call
    find(str1, str2);
 
    return 0;
}


Java
// Java program for the above approach
import java.io.*;
import java.util.*;
 
class GFG {
 
    static void find(String str1, String str2)
    {
 
        List > vec1
            = new ArrayList >();
 
        // Initialize vector of length 26
        for (int i = 0; i < 26; i++) {
            vec1.add(new ArrayList());
        }
 
        // Push indices of characters of str1
        for (int i = 0; i < str1.length(); i++)
            vec1.get(str1.charAt(i) - 'a').add(i);
 
        // Initialize the result & position
        int result = 1, position = 0;
 
        // Traverse the string str2
        for (int i = 0; i < str2.length(); i++)
        {
            char c = str2.charAt(i);
 
            // Return if no answer exist
            if (vec1.get(c - 'a').size() == 0)
            {
                result = -1;
                break;
            }
 
            List vec2 = vec1.get(c - 'a');
 
            // Lower bound of position
            int p = lower_bound(vec2, position);
 
            // If no index found
            if (p == vec2.size())
            {
 
                // Increment result
                result++;
                i--;
                position = 0;
                continue;
            }
 
            // Update the position
            else {
                position = vec2.get(p) + 1;
            }
        }
 
        // Print the result
        System.out.println(result);
    }
 
    // Driver Code
    static int lower_bound(List vec2, int position)
    {
        int low = 0, high = vec2.size() - 1;
 
        while (low < high) {
            int mid = (low + high) / 2;
            if (vec2.get(mid) < position)
                low = mid + 1;
            else
                high = mid;
        }
        return (vec2.get(low) < position) ? low + 1 : low;
    }
 
    public static void main(String[] args)
    {
        // Given string str1 & str2
        String str1 = "abb", str2 = "ababbbbb";
 
        // Function Call
        find(str1, str2);
    }
}


Python3
# Python3 program for the above approach
from bisect import bisect_left
 
# Function to find minimum operations
# required to form str2 by adding
# subsequences of str1
def find(str1, str2):
   
    # Initialize vector of length 26
    vec1 = [[] for i in range(26)]
 
    # Push indices of characters of str1
    for i in range(len(str1)):
        vec1[ord(str1[i]) - ord('a')].append(i)
 
    # Initialize the result & position
    result = 1
    position = 0
 
    # Traverse the str2
    i = 0
    while i < len(str2):
        c = str2[i]
 
        # Return if no answer exist
        if (len(vec1[ord(c) - ord('a')]) == 0):
            result = -1
            break
 
        # Pointer of vec1[c-'a']
        vec2 = vec1[ord(c) - ord('a')]
 
        # Lower bound of position
        p = bisect_left(vec2, position)
         
        #print(c)
 
        # If no index found
        if (p == len(vec2)):
 
            # Increment result
            result += 1
             
            #i-=1
            position = 0
            continue
             
        # Update the position
        else:
            i += 1
            position = vec2[p] + 1
 
    # Print the result
    print(result)
 
# Driver Code
if __name__ == '__main__':
   
    # Given str1 & str2
    str1 = "abb"
    str2 = "ababbbbb"
 
    # Function Call
    find(str1, str2)
 
# This code is contributed by mohit kumar 29


C#
// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
// Function to find minimum operations
// required to form str2 by adding
// subsequences of str1   
static void find(string str1, string str2)
{
    List> vec1 = new List>();
     
    // Initialize vector of length 26
    for(int i = 0; i < 26; i++)
    {
        vec1.Add(new List());
    }
     
    // Push indices of characters of str1
    for(int i = 0; i < str1.Length; i++)
    {
        vec1[str1[i] - 'a'].Add(i);
    }
     
    // Initialize the result & position
    int result = 1, position = 0;
     
    // Traverse the string str2
    for(int i = 0; i < str2.Length; i++)
    {
        char c = str2[i];
         
        // Return if no answer exist
        if (vec1.Count == 0)
        {
            result = -1;
            break;
        }
        List vec2 = vec1;
         
        // Lower bound of position
        int p = lower_bound(vec2, position);
         
        // If no index found
        if (p == vec2.Count)
        {
             
            // Increment result
            result++;
            i--;
            position = 0;
            continue;
        }
         
        // Update the position
        else
        {
            position = vec2[p] + 1;
        }
    }
     
    // Print the result
    Console.WriteLine(result);
}
 
static int lower_bound(List vec2,
                       int position)
{
    int low = 0, high = vec2.Count - 1;
     
    while (low < high)
    {
        int mid = (low + high) / 2;
         
        if (vec2[mid] < position)
        {
            low = mid + 1;
        }
        else
        {
            high = mid;
        }
    }
    return (vec2[low] < position) ?
                  low + 1 : low;
}
 
// Driver Code
static public void Main()
{
     
    // Given string str1 & str2
    string str1 = "abb", str2 = "ababbbbb";
     
    // Function Call
    find(str1, str2);
}
}
 
// This code is contributed by avanitrachhadiya2155


输出
4

时间复杂度: O(N + M log N)
辅助空间: O(M + N)