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

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

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

例子:

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

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

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

  1. 初始化地图M并存储S1中每个字符的出现频率
  2. 维护一个集合S ,该集合存储S1中存在的不同字符。
  3. M中减少S2中已经存在的S1字符的频率。
  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)