📌  相关文章
📜  最小的(大于S)长度为K的字符串,其字母为S的子集

📅  最后修改于: 2021-04-21 23:05:23             🧑  作者: Mango

给定长度为N的字符串S,该字符串由小写英文字母和整数K组成。找到在字典上长度为K的最小字符串T,以使其字母集合是S字母集合的子集,而T在字典上大于S注意:字母集是一个集合,而不是多集。例如,abadaba的字母集为{a,b,d}。

例子:

一个简单的解决方案是按长度顺序尝试所有长度为k的字符串。对于每个字符串,检查它是否大于S,如果是,则返回它。

以下是解决此问题的有效方法

让我们考虑两种情况:
1.如果N :在这种情况下,我们可以简单地将字符串S复制到字符串T中,以获取最多N个字符,而对于其余(K-N)个字符,我们可以将字符串S中的最小字符(最小ASCII值)附加到字符串T(K – N)次,因为我们必须找到字典上最小的字符串,该字符串刚好大于字符串S。

2.如果N≥K :在这种情况下,我们需要将字符串S复制到字符串T中(最多K个字符) ,然后对于字符串T,通过反向迭代,我们必须将所有这些字符替换为某个字符,直到字符串T变为在字典上大于字符串S的最小字符串。为此,我们可以执行以下操作:

  1. 将字符串S的字符存储在STL集中(当然,按排序顺序)
  2. 将字符串S复制到字符串T(最多K个字符)。
  3. 反向迭代,找到一个字符(让它在位置“ p”处找到),在该字符集中存在一些具有较大ASCII值的字符。
  4. 将此字符替换为集合中的字符。
  5. 将所有字符替换为第(p + 1)索引到K索引之间的最小字符。

插图:令S =“ bcegikmyyy”,N = 10,K =9。设置= {b,c,e,g,i,k,m,y}。将字符串S复制到T,最多K个字符T =“ bcegikmyy”。然后以相反的方向进行迭代,我们首先有“ y”,但集合中没有比“ y”更大的字符,所以继续前进。同样,我们有“ y”,现在继续前进,我们有“ m”,在其中存在更大的字符“ y”。将“ m”替换为“ y”,然后在向前的“ m”之后,将所有字符替换为最小字符,即“ b”。因此,字符串T变为T =“ bcegikybb”;

/* CPP Program to find the lexicographically
   smallest string T greater than S whose
   letters are subset of letters of S */
#include 
  
using namespace std;
  
// function to find the lexicographically
// smallest string greater than S
string findString(string S, int N, int K)
{
    // stores minimum character
    char minChar = 'z';
  
    // stores unique characters of
    // string in sorted order
    set found;
  
    // Loop through to find the minimum character
    // and stores characters in the set
    for (int i = 0; i < N; i++) {
        found.insert(S[i]);
        if (S[i] < minChar)
            minChar = S[i];
    }
  
    string T;
  
    // Case 1: If N < K
    if (N < K) {
  
        // copy the string S upto N characters
        T = S;
  
        // append minChar to make the remaining 
        // characters
        for (int i = 0; i < (K - N); i++)
            T += minChar;
    }
  
    // Case 2 :  If N >= K
    else {
        T = "";
  
        // copy the string S upto K characters
        for (int i = 0; i < K; i++)
            T += S[i];
  
        int i;
  
        // an iterator to the set
        set::iterator it;
  
        // iterating in reverse direction
        for (i = K - 1; i >= 0; i--) {
  
            // find the current character in the set
            it = found.find(T[i]);
  
            // increment the iterator
            it++;
  
            // check if some bigger character exists in set
            if (it != found.end())
                break;
        }
  
        // Replace current character with that found in set
        T[i] = *it;
  
        // Replace all characters after with minChar
        for (int j = i + 1; j < K; j++)
            T[j] = minChar;
    }
  
    return T;
}
  
// Driver Code to test the above function
int main()
{
    string S = "abc";
    int N = S.length();
  
    // Length of required string
    int K = 3;
  
    string T = findString(S, N, K);
    cout << "Lexicographically Smallest String "
            "greater than " << S
         << " is " << T << endl;
    return 0;
}
输出:
Lexicographically Smallest String greater than abc is aca

时间复杂度: O(N + K) ,其中N是给定字符串的长度,K是所需字符串的长度。