Codeforces 455B


タイトルリンク:http://codeforces.com/problemset/problem/455/B
标题:N文字列を与えて、2名の選手がいて、sは最初は空欄で、ラウンドごとに順番に中にアルファベットを記入して、sをN文字列の中の1つの文字列にして、もし更に中にアルファベットを記入できないならば負けて、負けた次のラウンドの先手、最後のラウンドの誰が勝つかを聞きます
考え方:全然……他人の問題解を参考にして、まず辞書の木でN文字列を保存して、深さで各ノードの状態をマークして、状態は4種類に分けます:0は勝負は後手で決めます(ずっと負けてずっと先手から最後のラウンドまで)、1は先手が必ず負けます(ずっと負けてずっと先手から最後のラウンドまで)、2は先手が必ず勝つのです(交代勝利、kのパリティが最終ラウンド負けを決める)、3はいずれも先手で勝負(最終ラウンドまで負け続ける)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define maxn 100030
using namespace std;

struct Tree
{
    int nxt[26],val;

    Tree init()
    {
        val=0;
        memset(nxt,0,sizeof(nxt));
    }

}tree[maxn*2];

int top,len;
char s[maxn];

void Insert(int lve,int now)
{
    if (now==len) return;

    int tem=s[now]-'a';
    if (tree[lve].nxt[tem]==0)
    {
        tree[top].init();
        tree[lve].nxt[tem]=top++;
    }
    Insert(tree[lve].nxt[tem],now+1);
}


int solve(int now)
{
    int& ans=tree[now].val,flag=1;
    ans=0;
    for (int i=0;i<26;i++)
    {
        if (tree[now].nxt[i]!=0)
        {
            flag=0;
            ans|=solve(tree[now].nxt[i]);
        }
    }
//cout<<now<<":"<<ans<<endl;
    if (flag)  ans=1;
    return 3-ans;

}


int main()
{
    int n,k;
    while (scanf("%d%d,",&n,&k)!=EOF)
    {
        tree[0].init();
        top=1;
        for (int i=0;i<n;i++)
        {
            scanf("%s",&s);
            len=strlen(s);
            Insert(0,0);
        }

        solve(0);
        int flag=tree[0].val;
        if (flag==1 || flag==0) printf("Second
"); else if (flag==2) { if (k%2==0) printf("Second
"); else printf("First
"); } else printf("First
"); } }