给定大小为N的两个字符串S1和大小为M的两个字符串S2 ,任务是找到按字典顺序排列的S1最小和最大的字母词,以使其包含字符串S2作为子字符串。
例子:
Input: S1 = “hheftaabzzdr”, S2 = “earth”
Output: abdearthfhzz, zzhfearthdba
Explanation:
The smallest anagram of the given string S1 with S2 as a substring is “abdearthfhzz”
The largest anagram of the given string S1 with s2 as a substring is “zzhfearthdba”
Input: S1 = “ethgakagmenpgs”, S2 = “geeks”
Output: aageeksgghmnpt, tpmnhgggeeksaa
Explanation:
The smallest anagram of the given string S1 with S2 as a substring is “aageeksgghmnpt”
The largest anagram of the given string S1 with S2 as a substring is “tpmnhgggeeksaa”
天真的方法:最简单的方法是找到S1的所有可能的字谜,并检查其中的任何一个字谜是否都包含S2作为子字符串。如果是,则在字典上找到最小和最大的字典。
时间复杂度: O(N!)
辅助空间: O(N)
有效的方法:我们的想法是首先生成由字符字典序最小字谜字符,然后通过颠倒最小字谜除了包含S2的子找到字典序最大的字谜。步骤如下:
- 初始化地图M并存储S1中每个字符的出现频率
- 维护一个集合S ,该集合存储S1中存在的不同字符。
- 从M中减少S2中已经存在的S1字符的频率。
- 初始化一个空字符串res ,该字符串将存储按字典顺序排列的最大字谜。
- 遍历集合S ,如果在遍历集合值时遇到字符串S2的第一个字符,请检查S2的第二个不同字符是否大于Set的当前字符。如果是这样,则将S2的所有字符添加到res 。
- 否则,请继续迭代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 charcter
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 charcter
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 charcter
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)