Andrew, Fedor and Alex are inventive guys. Now they invent the game with strings for two players.
Given a group of n non-empty strings. During the game two players build the word together, initially the word is empty. The players move in turns. On his step player must add a single letter in the end of the word, the resulting word must be prefix of at least one string from the group. A player loses if he cannot move.
Andrew and Alex decided to play this game k times. The player who is the loser of the i-th game makes the first move in the (i + 1)-th game. Guys decided that the winner of all games is the player who wins the last (k-th) game. Andrew and Alex already started the game. Fedor wants to know who wins the game if both players will play optimally. Help him.
The first line contains two integers, n and k (1 ≤ n ≤ 105; 1 ≤ k ≤ 109).
Each of the next n lines contains a single non-empty string from the given group. The total length of all strings from the group doesn't exceed 105. Each string of the group consists only of lowercase English letters.
If the player who moves first wins, print "First", otherwise print "Second" (without the quotes).
题意是说给定n个字符串,两个人做k次游戏,每一次游戏的规则是,首先有一个空串,两个人轮流向串中添加字符,必须满足这个字符串是给定的n个字符串中的其中一个的前缀,如果有人不能添加字符,则说明他输了这一次,下一次游戏由输的人先手,直到k次游戏结束,如果先手赢了输出first,否则输出second;
对于先手来说,
如果先手不仅有必胜的策略,而且有必败的策略,他可以先输k-1盘,然后赢一盘就可以了,先手赢;
如果先手有必胜的策略,没有必败的策略,那么两个人轮流先手,如果有奇数盘,则先手赢,偶数盘,则后手赢;
如果只有必败的策略,那么后手可以一直让他败下去,则后手赢;
我们可以利用n个字符串建立一个Trie树,用两个数组记录先手是否有必胜态,或者必败态,拿必胜态的数组举例子,因为先手只能拿到奇数层,后手拿到偶数层,如果这个点是偶数层的,那么它的子节点是先手取,如果子节点中存在必胜态,则这个节点也是必胜态。如果这个点是奇数层,子节点中存在必败态,则这个节点也是必败的。这样一直更新到根节点,得到先手是否有必胜的策略然后再判断是否有必败的策略就可以了。
#include<cstdio>
#include<cmath>
#include<cstring>
const int Maxn=100009;
int chd[Maxn][26],pre[Maxn],State[Maxn],State2[Maxn],level[Maxn];
int p,nn=1;
char str[Maxn];
void insert(char *str)
{
p=0;
int cnt=0;
while(*str)
{
cnt++;
int c=(*str++)-'a';
if(!chd[p][c])
{
memset(chd[nn],0,sizeof(chd[nn]));
chd[p][c]=nn++;
}
pre[chd[p][c]]=p;
p=chd[p][c];
level[p]=(cnt&1);
}
State[p]=State2[p]=(cnt&1)+1;
}
int main()
{
int n,k;
scanf("%d%d",&n,&k);
memset(chd[0],0,sizeof(chd[0]));
for(int i=0;i<n;i++)
{
scanf("%s",str);
insert(str);
}
for(int i=nn-1;i>0;i--)
{
int u=pre[i];
if(!State[u]) State[u]=State[i];
else
{
if(level[u]&&State[i]==1) State[u]=1;
if(!level[u]&&State[i]==2) State[u]=2;
}
}
for(int i=nn-1;i>0;i--)
{
int u=pre[i];
if(!State2[u]) State2[u]=State2[i];
else
{
if(!level[u]&&State2[i]==1) State2[u]=1;
if(level[u]&&State2[i]==2) State2[u]=2;
}
}
if(State[0]==2)
{
if(State2[0]==1) printf("First\n");
else
{
printf("%s\n", (k & 1) ? "First" : "Second");
}
}
else printf("Second\n");
return 0;
}