题意:给你一个有好多串的集合。一个字符串开始是空的,A和B两个人轮流在字符串后面加一个字符,保证得到的新字符串至少是集合的某一个串的前缀,谁不能加字母谁输。玩K局这个游戏,每局的输者是下一局的先手,问第K局谁赢?
题解:这个题当时只想到构造一颗前缀树,对前缀数进行SG函数的预处理,求出局势的情况。然后就是各种wa,不知道问题所在。比赛完有大神说要求先手制败,先手主动认输要下一局先手权。当时没想到啊……今天构造制败的时候,就是把所有初始化的0改成1。
代码:
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <iostream> #include <algorithm> #include <queue> #include <stack> #include <vector> #include <set> #include <string> using namespace std; #define For(i,a) for(i=0;i<a;i++) #define Foru(i,a,b) for(i=a;i<=b;i++) #define Ford(i,a,b) for(i=a;i>=b;i--) #define clr(ar,vel) memset(ar,vel,sizeof(ar)) #define PB push_back #define maxint 0x7fffffff struct node { int vel; int nex[26]; }; node s[500010]; int dfs(int x){ int end = 0; for(int i = 0; i < 26; i ++) { if( s[x].nex[i] != -1) dfs(s[x].nex[i]), end ++; } if( end == 0) { s[x].vel = 0; return 0; } int vel = 1; for(int i = 0; i < 26; i ++){ int w = s[x].nex[i]; if( w != -1){ vel &= s[w].vel; } } s[x].vel = vel^1; return s[x].vel; } int dfs2(int x){ // cout << x << endl; int end = 0; for(int i = 0; i < 26; i ++) { // cout << "s[].nex " << s[x].nex[i] << endl; if( s[x].nex[i] != -1) dfs2(s[x].nex[i]), end ++; } if( end == 0) { s[x].vel = 1; return s[x].vel; } int vel = 1; for(int i = 0; i < 26; i ++){ int w = s[x].nex[i]; if( w != -1){ vel &= s[w].vel; } } s[x].vel = vel^1; return s[x].vel; } int main(){ string str; int n, k, cnt; while( cin >> n >> k){ memset(s, -1, sizeof(s)); cnt = 1; for(int i = 0; i < n; i ++){ cin >> str; int head = 0; for(int i = 0; i < str.length(); i++){ int w = str[i] - 'a'; if( s[head].nex[w] == -1) { // cout << "cnt " << cnt << endl; s[head].nex[w] = cnt; cnt ++; } head = s[head].nex[w]; } } int d1 = dfs(0); int d2 = dfs2(0); // cout << d1 << ' ' << d2 << endl; if( d1 && d2) cout << "First" << endl; else if( d1 ){ if( k%2 ) cout << "First" << endl; else cout << "Second" << endl; } else { cout << "Second" << endl; } } return 0; }