📜  使用Trie分配用户名的程序

📅  最后修改于: 2021-04-17 13:20:49             🧑  作者: Mango

假设有一个n个用户的队列,您的任务是为他们分配一个用户名。该系统以以下方式工作。每个用户都喜欢以字符串s的形式进行的首选登录,该登录仅由小写字母和数字组成。用户名按以下顺序分配:s,s0,s1,s2….s11…。意味着首先检查s是否可用,如果已被占用,则对其进行检查;如果s0已被空闲,则对其进行检查;是否已被占用,则对s1,进行此类检查……如果将用户名分配给一个用户,则该用户将被其他用户占用。在他排队之后。

例子

我们使用Trie解决了这个问题。我们不使用具有26个子代的普通Trie,而是使用一个Trie,其中的节点具有36个子代26个字母(az)和10个从(0-9)的数字。除此之外,Trie的每个节点都将具有bool变量,当插入在该节点结尾的字符串时,布尔变量将变为true,也将有一个int变量,也可以称其为add,它的初始值为-1,并且假设该字符串为geek并且此int变量等于-1,则意味着我们将直接返回首次请求的geek,但假设它是12,则意味着字符串geek,geek0…..geek12已存在于Trie中。
脚步
第1步:维护Trie,如上所述。
步骤2:对于每个给定名称,检查用户给定的字符串是否不在Trie中,然后返回相同的字符串,否则从i = add + 1开始(上面讨论了add),然后开始检查是否将i与输入字符串连接起来是否存在于Trie中(如果不存在),则将其返回并设置add = i并将其插入到Trie中,否则递增i
假设字符串是geek且i = 5检查geek5是否在Trie中,如果不存在则返回geek5 set add for geek = 5在grie中插入geek5,如果不存在,则对geek6遵循相同的步骤,直到找到一个字符串在Trie中不存在。

// C++ program to assign usernames to users
#include 
using namespace std;
  
#define MAX_CHAR 26
  
struct additional {
  
    // is checks if the current node is
    // leaf node or not
    bool is;
  
    // add counts number of concatenations
    // of string are present in Trie
    int add;
};
  
// represents Trie node
struct Trie {
  
    // MAX_CHAR character children
    Trie* character[MAX_CHAR];
  
    // 10 numbers (from 0 to 9)
    Trie* number[10];
  
    // one additional struct children
    additional a;
};
  
// function to get new node
Trie* getnew()
{
    // initialising the Trie node
    Trie* node = new Trie;
    node->a.is = false;
    node->a.add = -1;
    for (int i = 0; i < MAX_CHAR; i++)
        node->character[i] = NULL;
    for (int i = 0; i < 10; i++)
        node->number[i] = NULL;
    return node;
}
  
// inserting a string into Trie
void insert(Trie*& head, string s)
{
    Trie* curr = head;
    for (int i = 0; i < s.length(); i++) {
        if (s[i] - 'a' < 0) {
            if (curr->number[s[i] - '0'] == NULL) {
                curr->number[s[i] - '0'] = getnew();
            }
            curr = curr->number[s[i] - '0'];
        }
        else {
            if (curr->character[s[i] - 'a'] == NULL)
                curr->character[s[i] - 'a'] = getnew();
            curr = curr->character[s[i] - 'a'];
        }
    }
    curr->a.is = true;
}
  
// returns the structure additional
additional search(Trie* head, string s)
{
    additional x;
    x.is = false;
    x.add = -1;
  
    // if head is null directly return additional x
    if (head == NULL)
        return x;
    Trie* curr = head;
  
    // checking if string is present or not and
    // accordingly returning x
    for (int i = 0; i < s.size(); i++) {
        if (s[i] - 'a' < 0) {
            curr = curr->number[s[i] - '0'];
        }
        else
            curr = curr->character[s[i] - 'a'];
        if (curr == NULL)
            return x;
    }
    x.is = curr->a.is;
    x.add = curr->a.add;
    return x;
}
  
// special function to update add variable to z
void update(Trie* head, string s, int z)
{
    Trie* curr = head;
    for (int i = 0; i < s.size(); i++) {
        if (s[i] - 'a' < 0)
            curr = curr->number[s[i] - '0'];
        else
            curr = curr->character[s[i] - 'a'];
    }
    curr->a.add = z;
}
  
void printUsernames(string username[], int n)
{
    // Initialing a Trie root
    Trie* head = getnew();
  
    // Assigning usernames one by one
    for (int i = 0; i < n; i++) {
        string s = username[i];
        additional x = search(head, s);
  
        // if string is not present directly return it
        if (x.is == false) {
            cout << s << endl;
            insert(head, s);
        }
  
        // to_string(x) converts integer x into string
        else if (x.is == true) {
  
            // start from x.add+1
            int y = x.add + 1;
            string x = s;
  
            // continuing searching the string
            // until a free username is found
            while (1 < 2) {
  
                // if free username is found
                if (search(head, x + to_string(y)).is == false) {
  
                    // print it inser it and update add
                    cout << x << y << endl;
                    insert(head, x + to_string(y));
                    update(head, s, y);
                    break;
                }
                // else increment y
                else if (search(head, x + to_string(y)).is == true)
                    y++;
            }
        }
    }
}
  
// driver function
int main()
{
    string name[] = { "geek", "geek0", "geek1", "geek" };
    int n = sizeof(name) / sizeof(name[0]);
    printUsernames(name, n);
    return 0;
}
输出:
geek
geek0
geek1
geek2