解いてみた。「Bランク：みんなでしりとり」

# 問題
[「Bランク：みんなでしりとり」](https://paiza.jp/works/mondai/b_rank_skillcheck_archive/word_chain)

# コード
Javaで解いてみました。

``` Java
import java.util.*;

public class Main {
    public static final char FREE = '*';

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        int nN = sc.nextInt();
        int nK = sc.nextInt();
        int nM = sc.nextInt();
        
        // 単語セットの生成
        HashSet<String> hsWords = new HashSet<String>();
        for (int i = 0; i < nK; i++) {
            String s = sc.next();
            hsWords.add(s);
        }
        
        // 初期設定
        int nTurn = 1;          // 手番
        char cFirstChar = FREE; // 頭の文字
        int nRestPlayer = nN;   // 残り人数 （問題文より、0になることはない）

        boolean[] bRestPlayers = new boolean[nN+1];
        for (int i = 1; i <= nN; i++) {
            bRestPlayers[i] = true; // 残っている
        }
        
        // ゲーム開始
        for (int i = 0; i < nM; i++) {
            boolean bClear = false;
            String s = sc.next();
            if (hsWords.contains(s)) {  // 発言した単語が、集合に存在し、かつ未使用であるか？
                hsWords.remove(s);  // 使用済みのため集合から消去
                
                char cFirst = getFirstChar(s);
                if ((cFirstChar == FREE) || (cFirstChar == cFirst)) {
                    char cLast = getLastChar(s);
                    if (cLast != 'z') {
                        // clear!
                        bClear = true;
                        cFirstChar = cLast;
                    } 
                }
            }
            
            if (!bClear) {  // クリアできなかった場合
                // プレイヤー脱落
                bRestPlayers[nTurn] = false;
                nRestPlayer--;
                cFirstChar = FREE;
            }
            
            // 手番を次のプレイヤーにする
            while(nRestPlayer > 0) {
                nTurn++;
                if (nTurn > nN) { nTurn = 1; }
    
                if (bRestPlayers[nTurn]) {  // 手番のプレイヤーが残っていたら、ループ終了
                    break;
                }
            }
        }

        // 結果出力        
        System.out.println(nRestPlayer);    // 残り人数
        for (int i = 1; i <= nN; i++) {
            if (bRestPlayers[i]) {
                System.out.println(i);      // 残ったプレイヤーの番号
            }
        }
    }
    
    private static char getFirstChar(String s) {
        return s.charAt(0);
    }
    
    private static char getLastChar(String s) {
        return s.charAt(s.length() - 1);
    }
}
```

# 解説
## 標準入力からの数値の読み取り
Scanner インスタンスを作り、nextInt()メソッドで数値を取得しています。
## 単語セットの作成
HashSet\<String\> インスタンスを作り、標準入力から next() メソッドで取得した文字列を格納しています。
## 初期設定
+ 手番を1番のプレイヤーに設定
+ 最初の文字をFREE（指定なし）に設定
+ 残りプレイヤー人数をnN人に設定
+ 残りプレイヤーの状況を表す配列を作り、true（残っている）で初期化
## ゲーム開始
発言した文字列 s を取得します。
### ルール１〜４のチェック
#### s が単語セットに含まれているか？
+ ルール１) 「発言は、単語リストにある K 個の単語のうちのいずれかの単語でなければならない。」
+ ルール3) 「今までに発言された単語を発言してはならない。」

を満たすかのチェックです。なお、この時点で「発言された単語」になるので単語セットから削除します。

#### s の最初の文字のチェック
+ ルール２） 「最初の人以外の発言の頭文字は、直前の人の発言の最後の文字と一緒でなければならない。」

を満たすかのチェックです。ただし、最初の人、および、脱落した人の次の手番の人は、指定なし（FREE）となります。

#### s の最後の文字のチェック
+ ルール4) 「z で終わる単語を発言してはならない。」

を満たすかのチェックです。

### チェックを一通りクリアできたか？
#### クリアした場合
何もしません。（次の処理へ。）
#### クリアできなかった場合
プレイヤーの脱落処理を行います。
### 次の手番に移動
nTurn をインクリメント（nNを超えたら1に戻る）していき、脱落していないプレイヤーに当たったら、その人の手番にします。
（なお、問題文より、残りプレイヤーが1人以上いることは保証されています。）
## 結果の出力
+ 　残りプレイヤーの人数を表示
+ 　残りプレイヤーの番号を全て表示