题意:给你一个有好多串的集合。一个字符串开始是空的,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;
}