UVALive 7832 Dictionary Game解题报告(字典树+树上删边游戏)

question

    We all know the famous game scrabble, where we want to make words using tiles. We will play a game with words. But it is reverse of scrabble. Here instead of making words we want to destroy them. It is a two player game.
    The game starts with a dictionary of words. At each move, the current player chooses a word of his choice (not necessarily from the dictionary). The constraints for choosing the word is, it must match the prefix of any (one or more) of the current dictionary words. When a player chooses a word as its move, all the dictionary words that has a prefix equal to the
chosen word, are split into two parts:
        1. The matched part without the last character of the chosen word.
        2. The unmatched part starting from the last character of the chosen word.
    We remove all the unmatched part from the dictionary and keep only the matched part in the dictionary. The words that don’t have matched prefix with the chosen word are kept intact in the dictionary. In this situation the next player makes its move in the same fashion. If the chosen word is of length 1, then all the dictionary words starting with that character will be removed.
    For example, if we have a dictionary consisting the following words:
               bangladesh
               bangalore
               band
               bandana
    Now if the first player chooses the word bang then after the move the dictionary will become:
                ban
                ban
                band
                bandana
    A player loses, when it cannot make a valid move. Given the dictionary of words, who will win if both players played optimally? To make it more interesting, can you find out who will win if you update the dictionary by adding new words?
    Formally, you will be given few operations where you need to add a new word to the dictionary. After adding you need to calculate the winner between player 1 and 2 for the current dictionary. These added words are permanent. Means each of these added words will remain in the dictionary for that particular test case.

Input
    First line consists of an integer T , which is the number of test cases (T ≤ 10).
    Each case will start with an integer N (0 N ≤ 50000), the number of words in the dictionary. Next N lines will contain dictionary words DW. Length of each DW will be less than or equal to 40.
    Next line will contain an integer number Q, the number of operations (0 Q ≤ 50000).

    Next Q lines will contain query words QW. Each QW is the word that you now want to add to the current dictionary. Let’s call these Query words. Length of each QW will be less than or equal to 40. All the dictionary words and query words will only consist of lower case letters.
Output
    For each query word QW, you have to find out who will win, if you add QW to the current dictionary. First print the case number, then for each query print ‘1’ or ‘2’ based on whether player 1 or 2 will win.
Sample Input
2
4
bangladesh
bangalore
band
bandana
2
egg
apple
1
orange
2
cat
tiger
Sample Output
Case 1:
2
1
Case 2:
1
2

 

直接根据输入建立字典树,然后树上删边求sg即可

 

 

#include cstdio
#include queue
#include cmath
#include cstdlib
#include cstring
#include iostream
#include map
#include algorithm
#include vector
#define OUT freopen("out.txt","w",stdout)
#define mem(a,b) memset(a,b,sizeof (a))
#define DEBUG(a) cout  (a)  endl
#define lowbit(a) ((a)(-a))
#define IN freopen("in.txt","r",stdin)
#define IO ios::sync_with_stdio(false);\
        cin.tie(0);\
        cout.tie(0);
using namespace std;
typedef long long ll;
const int maxn = 5e6+10;
const int PI = acos(-1);
const int MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
struct tire{
    int son[26];
    int f;
}a[maxn];
int sg[maxn];
int tot;
string s;

int _insert(){
    int root = 0;
    for(int i=0;is.size();i++){
        int buf = s[i] - 'a';
        if(!a[root].son[buf]){
            a[root].son[buf]  = ++tot;
            a[tot].f = root;
        }
        root = a[root].son[buf];
    }
    return root;
}

void cal(int x){
    sg[x] = 0;
    for(int i=0;i26;i++)
        if(a[x].son[i])
            sg[x] ^= sg[a[x].son[i]] + 1;
}
void dfs(int x){
    for(int i=0;i26;i++)
        if(a[x].son[i])
            dfs(a[x].son[i]);
    cal(x);
}

void update(int x){
    while(x){
        cal(x);
        x = a[x].f;
    }
    cal(0);
}

int main(){
   // IN;
    int t,n;
    cin  t;
    int step = 0;
    while(t--){
        //DEBUG(t);
        //    DEBUG("");
        tot = 0;
        printf("Case %d:\n",++step);
        cin n;
        for(int i=0;in;i++){
            cin  s;
            _insert();
        }
        dfs(0);
        cin  n;
        for(int i=0;in;i++){
            cin  s;
            update(_insert());
            DEBUG(sg[0]?"1":"2");
        }
        for(int i=0;i=tot;i++){
            a[i].f = 0;
            mem(a[i].son,0);
        }
    }
    return 0;
}

 

最新回复(0)
/jishudH_2FMa90pY6h0nXVA3bopnaq9stjUTy1cadBkJAQcqKA_3D4858257
8 简首页