📌  相关文章
📜  包含另一个字符串作为其子字符串的字符串的字典序最小和最大字谜

📅  最后修改于: 2021-09-06 05:05:25             🧑  作者: Mango

给定两个大小为N 的字符串S1和大小为M 的S2 ,任务是找到S1的字典序最小和最大的字谜,使其包含字符串S2作为子字符串。

例子:

朴素的方法:最简单的方法是找到S1 的所有可能的字谜,并检查这些字谜中是否有任何一个包含S2作为子字符串。如果是,则找到其中字典序最小的和最大的。

时间复杂度: O(N!)
辅助空间: O(N)

有效的方法:我们的想法是首先生成由字符字典序最小字谜字符,然后通过颠倒最小字谜除了包含S2的子找到字典序最大的字谜。以下是步骤:

  1. 初始化映射M并存储每个字符出现在S1 中的频率
  2. 维护一个 Set S ,它存储S1 中存在的不同字符。
  3. 减少S1中已经存在于S2 中的M字符的频率。
  4. 初始化一个空字符串res ,它将存储字典序最大的字谜。
  5. 迭代集合S ,如果在遍历集合值时遇到字符串S2的第一个字符,则检查S2的第二个不同字符是否大于Set的当前字符。如果是,则将S2 的所有字符添加到res
  6. 否则,继续迭代Set并将字符添加到res

下面是上述方法的实现:

C++14
// C++ program for the above approach
#include 
using namespace std;
 
// Function to find the lexicographically
// smallest anagram of string
// which contains another string
pair lexico_smallest(string s1,
                                  string s2)
{
 
    // Initializing the map and set
    map M;
    set S;
    pair pr;
 
    // Iterating over s1
    for (int i = 0; i <= s1.size() - 1; ++i) {
 
        // Storing the frequency of
        // characters present in s1
        M[s1[i]]++;
 
        // Storing the distinct
        // characters present in s1
        S.insert(s1[i]);
    }
 
    // Decreasing the frequency of
    // characters from M that
    // are already present in s2
    for (int i = 0; i <= s2.size() - 1; ++i) {
        M[s2[i]]--;
    }
 
    char c = s2[0];
    int index = 0;
    string res = "";
 
    // Traversing alphabets
    // in sorted order
    for (auto x : S) {
 
        // If current character of set
        // is not equal to current
        // character of s2
        if (x != c) {
            for (int i = 1; i <= M[x]; ++i) {
                res += x;
            }
        }
        else {
 
            // If element is equal to
            // current character of s2
            int j = 0;
            index = res.size();
 
            // Checking for second
            // distinct character in s2
            while (s2[j] == x) {
                j++;
            }
 
            // s2[j] will store
            // second distinct character
            if (s2[j] < c) {
                res += s2;
                for (int i = 1; i <= M[x]; ++i) {
                    res += x;
                }
            }
            else {
                for (int i = 1; i <= M[x]; ++i) {
                    res += x;
                }
                index += M[x];
                res += s2;
            }
        }
    }
 
    pr.first = res;
    pr.second = index;
 
    // Return the answer
    return pr;
}
 
// Function to find the lexicographically
// largest anagram of string
// which contains another string
string lexico_largest(string s1, string s2)
{
 
    // Getting the lexicographically
    // smallest anagram
    pair pr = lexico_smallest(s1, s2);
 
    // d1 stores the prefix
    string d1 = "";
    for (int i = pr.second - 1; i >= 0; i--) {
        d1 += pr.first[i];
    }
 
    // d2 stores the suffix
    string d2 = "";
    for (int i = pr.first.size() - 1;
         i >= pr.second + s2.size(); --i) {
        d2 += pr.first[i];
    }
 
    string res = d2 + s2 + d1;
 
    // Return the result
    return res;
}
 
// Driver Code
int main()
{
    // Given two strings
    string s1 = "ethgakagmenpgs";
    string s2 = "geeks";
 
    // Function Calls
    cout << lexico_smallest(s1, s2).first
         << "\n" ;
    cout << lexico_largest(s1, s2);
 
    return (0);
}


Java
// Java program for the above approach
import java.lang.*;
import java.io.*;
import java.util.*;
 
class GFG{
     
// Function to find the lexicographically
// smallest anagram of string
// which contains another string
static String[] lexico_smallest(String s1, 
                                String s2)
{
     
    // Initializing the map and set
    Map M = new HashMap<>();
    Set S = new TreeSet<>();
    
    // Iterating over s1
    for(int i = 0; i <= s1.length() - 1; ++i)
    {
         
        // Storing the frequency of
        // characters present in s1
        if (!M.containsKey(s1.charAt(i)))
            M.put(s1.charAt(i), 1);
        else
            M.replace(s1.charAt(i),
                M.get(s1.charAt(i)) + 1);
   
        // Storing the distinct
        // characters present in s1
        S.add(s1.charAt(i));
    }
   
    // Decreasing the frequency of 
    // characters from M that
    // are already present in s2
    for(int i = 0; i <= s2.length() - 1; ++i)
    {
        if (M.containsKey(s2.charAt(i)))
            M.replace(s2.charAt(i),
                M.get(s2.charAt(i)) - 1);
    }
   
    char c = s2.charAt(0);
    int index = 0;
    String res = "";
   
    // Traversing alphabets
    // in sorted order
    Iterator it = S.iterator();
    while (it.hasNext())
    {
        char x = it.next();
         
        // If current character of set
        // is not equal to current 
        // character of s2
        if (x != c)
        {
            for(int i = 1; i <= M.get(x); ++i)
            {
                res += x;
            }
        }
        else
        {
             
            // If element is equal to 
            // current character of s2
            int j = 0;
            index = res.length();
             
            // Checking for second
            // distinct character in s2
            while (s2.charAt(j) == x)
            {
                j++;
            }
             
            // s2[j] will store
            // second distinct character
            if (s2.charAt(j) < c)
            {
                res += s2;
                for(int i = 1; i <= M.get(x); ++i)
                {
                    res += x;
                }
            }
            else
            {
                for(int i = 1; i <= M.get(x); ++i)
                {
                    res += x;
                }
                index += M.get(x);
                res += s2;
            }
        }
    }
    String pr[] = {res, index + ""};
    return pr;
}
 
// Function to find the lexicographically
// largest anagram of string
// which contains another string
static String lexico_largest(String s1, String s2)
{
     
    // Getting the lexicographically
    // smallest anagram
    String pr[] = lexico_smallest(s1, s2);
   
    // d1 stores the prefix
    String d1 = "";
    for(int i = Integer.valueOf(pr[1]) - 1;
            i >= 0; i--)
    {
        d1 += pr[0].charAt(i);
    }
   
    // d2 stores the suffix
    String d2 = "";
    for(int i = pr[0].length() - 1;
            i >= Integer.valueOf(pr[1]) +
                                 s2.length();
            --i)
    {
        d2 += pr[0].charAt(i);
    }
     
    String res = d2 + s2 + d1;
     
    // Return the result
    return res;
}
 
// Driver Code
public static void main (String[] args)
{
     
    // Given two strings
    String s1 = "ethgakagmenpgs";
    String s2 = "geeks";
     
    // Function Calls
    System.out.println(lexico_smallest(s1, s2)[0]);
    System.out.println(lexico_largest(s1, s2));
}
}
 
// This code is contributed by jyoti369


Python3
# Python program for the above approach
 
# Function to find the lexicographically
# smallest anagram of string
# which contains another string
def lexico_smallest(s1, s2):
 
    # Initializing the dictionary and set
    M = {}
    S = []
    pr = {}
 
    # Iterating over s1
    for i in range(len(s1)):
 
        # Storing the frequency of
        # characters present in s1
        if s1[i] not in M:
            M[s1[i]] = 1
        else:
            M[s1[i]] += 1
         
        # Storing the distinct
        # characters present in s1
        S.append(s1[i])
    S = list(set(S))
    S.sort()
 
    # Decreasing the frequency of
    # characters from M that
    # are already present in s2
    for i in range(len(s2)):
        if s2[i] in M:
            M[s2[i]] -= 1
 
    c = s2[0]
    index = 0
    res = ""
 
    # Traversing alphabets
    # in sorted order
    for x in S:
       
        # If current character of set
        # is not equal to current
        # character of s2
        if(x != c):
            for i in range(1, M[x] + 1):
                res += x
        else:
           
            # If element is equal to
            # current character of s2
            j = 0
            index = len(res)
 
            # Checking for second
            # distinct character in s2
            while(s2[j] == x):
                j += 1
                 
            # s2[j] will store
            # second distinct character
            if(s2[j] < c):
                res += s2
 
                for i in range(1, M[x] + 1):
                    res += x
            else:
                for i in range(1, M[x] + 1):
                    res += x
                index += M[x]
                res += s2       
    pr[res] = index
     
    # Return the answer
    return pr
 
# Function to find the lexicographically
# largest anagram of string
# which contains another string
def lexico_largest(s1, s2):
   
    # Getting the lexicographically
    # smallest anagram
    Pr = dict(lexico_smallest(s1, s2))
 
    # d1 stores the prefix
    d1 = ""
    key = [*Pr][0]
    for i in range(Pr.get(key) - 1, -1, -1):
        d1 += key[i]
 
    # d2 stores the suffix
    d2 = ""
    for i in range(len(key) - 1, Pr[key] + len(s2) - 1, -1):
        d2 += key[i]
    res = d2 + s2 + d1
 
    # Return the result
    return res
 
# Driver Code
 
# Given two strings
s1 = "ethgakagmenpgs"
s2 = "geeks"
 
# Function Calls
print( *lexico_smallest(s1, s2))
print(lexico_largest(s1, s2))
 
# This code is contributed by avanitrachhadiya2155


输出:
aageeksgghmnpt
tpnmhgggeeksaa

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

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live