Problem: agc044_d
Difficulty: hard
Categories: greedy, search
Time limit: 2000 ms, memory limit: 1024 MB

### Problem Statement

**This is an interactive task.**

You have to guess a secret password $S$.
A password is a nonempty string whose length is at most $L$.
The characters of a password can be lowercase and uppercase english letters (a, b,..., z, A, B,..., Z) and digits (0, 1,..., 9).

In order to guess the secret password $S$ you can ask queries.
A query is made of a valid password $T$, the answer to such query is the edit distance between $S$ and $T$ (the operations considered for the edit distance are: removal, insertion, substitution).
You can ask at most $Q$ queries.

**Note**: For a definition of edit distance (with operations: removal, insertion, substitution), see this wikipedia page.

### Constraints

* $L = 128$
* $Q = 850$
* The secret password $S$ is chosen before the beginning of the interaction.

### Interaction

To ask a query, print on Standard Output (with a newline at the end)

```? $T$
```

The string $T$ must be a valid password.

The answer $ans$ to each query shall be read from Standard Input in the form:

```
$ans$
```

As soon as you have determined the hidden password $S$, you should print on Standard Output (with a newline at the end)

```! $S$
```

and terminate your program.

### Judgement

* **After each output, you must flush Standard Output.** Otherwise you may get `TLE`.
* After you print (your guess of) the hidden password, the program must be terminated immediately. Otherwise, the behavior of the judge is undefined.
* If the password you have determined is wrong, you will get `WA`.
* If you ask a malformed query (for example because the string is not a valid password, or you forget to put `?`) or if your program crashes or if you ask more than $Q$ queries, the behavior of the judge is undefined (it does not necessarily give `WA`).

### Samples

In the only sample testcase of this problem the hidden password is `Atcod3rIsGreat`.

The following one is an example of interaction if $S=$`Atcod3rIsGreat`.

| Input | Output |
| --- | --- |
|  | $\texttt{? AtcoderIsBad}$ |
| $5$ |  |
|  | $\texttt{? AtcoderIsGreat}$ |
| $1$ |  |
|  | $\texttt{! Atcod3rIsGreat}$ |

Non-adaptive interactor (C++):
#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;

static long long queries = 0;
static long long query_limit = 850;
const int HARD_CAP = 20000;

static string hidden_password;


static void log_metrics() {
    try {
        tout << "queries=" << queries << endl;
        tout << "query_limit=" << query_limit << endl;
    } catch (...) {
        
    }
}


static void finish(TResult verdict, const string& msg) {
    log_metrics();
    quitf(verdict, "%s", msg.c_str());
}

bool is_valid_char(char c) {
    return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9');
}

bool is_valid_password(const string& s) {
    if (s.empty()) return false;
    if (s.length() > 128) return false;
    for (char c : s) {
        if (!is_valid_char(c)) return false;
    }
    return true;
}


int get_edit_dist(const string& s, const string& t) {
    int n = s.length();
    int m = t.length();
    vector<vector<int>> dp(n + 1, vector<int>(m + 1));

    for (int i = 0; i <= n; i++) dp[i][0] = i;
    for (int j = 0; j <= m; j++) dp[0][j] = j;

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            int cost = (s[i - 1] == t[j - 1] ? 0 : 1);
            dp[i][j] = min({
                dp[i - 1][j] + 1,    
                dp[i][j - 1] + 1,    
                dp[i - 1][j - 1] + cost 
            });
        }
    }
    return dp[n][m];
}

int main(int argc, char** argv) {
    
    registerInteraction(argc, argv);
    atexit(log_metrics);

    
    
    hidden_password = inf.readToken();
    
    
    if (!is_valid_password(hidden_password)) {
        
        
        
    }
    
    
    query_limit = 850;

    
    while (true) {
        
        if (queries >= HARD_CAP) {
            finish(_pe, "Hard query limit exceeded (infinite loop?)");
        }

        string token;
        if (!(cin >> token)) {
            
            finish(_pe, "Unexpected EOF (no answer provided)");
        }

        if (token == "!") {
            
            string ans;
            if (!(cin >> ans)) {
                finish(_pe, "Unexpected EOF after '!'");
            }
            
            
            if (ans == hidden_password) {
                finish(_ok, "Correct password");
            } else {
                finish(_wa, "Wrong password");
            }
        } else {
            
            string t;
            if (token == "?") {
                
                if (!(cin >> t)) {
                    finish(_pe, "Unexpected EOF after '?'");
                }
            } else {
                
                
                
                t = token;
            }

            
            queries++;
            
            
            if (queries % 10 == 0) {
                log_metrics();
            }

            
            if (!is_valid_password(t)) {
                finish(_pe, format("Invalid query string: '%s' (length > 128 or invalid chars)", compress(t).c_str()));
            }

            
            int d = get_edit_dist(hidden_password, t);
            cout << d << endl; 
        }
    }

    return 0;
}


Adaptive interactor (C++):

Test generator (C++):
#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;

const string ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

int main(int argc, char* argv[]) {
    registerGen(argc, argv, 1);

    
    
    string mode = opt<string>("mode", "non");

    
    long long seed_val = atoll(argv[1]);
    
    
    const int MAX_L = 128;
    string S = "";

    
    if (seed_val == 1) {
        
        int len = MAX_L;
        for (int i = 0; i < len; ++i) {
            S += ALPHABET[rnd.next(0, (int)ALPHABET.size() - 1)];
        }
    } else if (seed_val == 2) {
        
        int len = MAX_L;
        char c = ALPHABET[rnd.next(0, (int)ALPHABET.size() - 1)];
        S = string(len, c);
    } else if (seed_val == 3) {
        
        int len = 1;
        S += ALPHABET[rnd.next(0, (int)ALPHABET.size() - 1)];
    } else if (seed_val == 4) {
        
        int len = MAX_L;
        char c1 = ALPHABET[rnd.next(0, (int)ALPHABET.size() - 1)];
        char c2;
        do {
            c2 = ALPHABET[rnd.next(0, (int)ALPHABET.size() - 1)];
        } while (c1 == c2);
        for (int i = 0; i < len; ++i) {
            S += (i % 2 == 0 ? c1 : c2);
        }
    } else {
        
        
        
        
        int len;
        int t = rnd.next(1, 100);
        if (t <= 5) len = rnd.next(1, 10);           
        else if (t <= 15) len = rnd.next(11, 60);    
        else len = rnd.next(61, MAX_L);              

        
        
        string current_alpha;
        int alpha_strategy = rnd.next(1, 100);
        
        if (alpha_strategy <= 20) {
            
            int sz = rnd.next(1, 4);
            string temp = ALPHABET;
            shuffle(temp.begin(), temp.end());
            current_alpha = temp.substr(0, sz);
        } else if (alpha_strategy <= 60) {
            
            int sz = rnd.next(5, 20);
            string temp = ALPHABET;
            shuffle(temp.begin(), temp.end());
            current_alpha = temp.substr(0, sz);
        } else {
            
            current_alpha = ALPHABET;
        }

        
        for (int i = 0; i < len; ++i) {
            S += current_alpha[rnd.next(0, (int)current_alpha.size() - 1)];
        }
    }

    
    
    
    if (mode == "non") {
        cout << S << endl;
    } else {
        
        
        cout << S << endl;
    }

    return 0;
}