Google - Zombie Lab Password

题目描述

You've been trying to gain entry to the zombie lab for a while now. To open the door, you need to enter a password on the keyboard connected to it. To that end, you've been watching and meticulously recording everything you can see around the entrance. You've finally had a big break when you were able to acquire the notes of the zombie technicians:

Input

anagram

Rotation table

anagram$
nagram$a
agram$an
gram$ana
ram$anag
am$anagr
m$anagra
$anagram

Sort table

agram$an
am$anagr
anagram$
gram$ana
m$anagra
nagram$a
ram$anag
$anagram

Output

nr$aaagm

After carefully studying the notes, you've managed to decipher them. The string is treated as if it is wrapped around a ring, and that ring is rotated.

  1. Start with the input string (Input)
  2. Append an end marker ($)
  3. Take the word and rotate it by moving the first character to the end.
  4. Add each rotation to a table and repeat 3 until you get back to the original order (Rotation table)
  5. Sort the rotations, with the end marker sorting to the end (Sort table)
  6. Take the final column as the output (Output)

The note also contains something that you have reason to suspect is the password after having been put through the above process.

思路解析

这道题给定了输出,让我们还原出输入来。观察输出nr$aaagm,不难建立 Sort table 如下:

  a -> n
  a -> r
  a -> $
  g -> a
  m -> a
  n -> a
  r -> g
  $ -> m

其中左侧为根据nr$aaagm得到的所有字符的排序结果。所有右侧字符均为左侧字符的上一个元素。

因为存在重复的元素,这道题采用DFS的做法。

  1. 确定最后一位元素
  2. 查询Sort table,得到其上一位元素加入到结果(password),如果存在多个查询结果,则取第一个尝试
  3. 如果password的长度等于输入的字符串长度,DFS结束,得到password,否则回退至第二步。

经过测试,这里复合条件的结果不止一个,因此不能找到一个结果后停止搜寻。

代码实现

#include <iostream>
#include <string>
#include <unordered_map>
#include <algorithm>
#include <vector>

using namespace std;

class Solution {
private:
    std::vector<char> heads;
    std::vector<char> tails;
    void dfs(std::string &password, std::unordered_map<char, int> &count);
public:
    void zombiePassword(std::string input);
    std::vector<std::string> possiblePasswords;
};

void Solution::dfs(std::string &password, std::unordered_map<char, int> &count) {
    if(password.size() == heads.size()) {
        possiblePasswords.push_back(password.substr(0, password.length() - 1));
        count[password[0]]++;
        password = password.substr(1, password.length() - 1);
        return;
    }
    char cur = password[0];
    for(int i = 0; i < heads.size(); i++) {
        if(heads[i] == cur && count[tails[i]] > 0) {
            password = std::string(1, tails[i]) + password;
            count[tails[i]]--;
            dfs(password, count);
        }
    }
    count[password[0]]++;
    password = password.substr(1, password.length() - 1);
}

void Solution::zombiePassword(std::string input) {
    std::unordered_map<char, int> count;
    for(auto s : input) {
        if(s != '$') {
			count[s]++;
            heads.push_back(s);
        }
        tails.push_back(s);
    }
    std::sort(heads.begin(), heads.end());
    heads.push_back('$');

    std::string password = "$";
    dfs(password, count);
}

int main(int argc, char** argv) {
    string input;
    cin >> input;

    Solution s;
    s.zombiePassword(input);
    
    for(auto password : s.possiblePasswords)
        cout << password << endl;

    return 0;
}
posted @ 2021-07-04 17:59  行者橙子  阅读(41)  评论(0编辑  收藏  举报