このTopCoderの問題はこちらで見ることができる(要TopCoder登録 & 問題文は英語)。それでは、問題について説明する。
多人数協力型のオンラインゲームを作っている。チームのプレーヤーはゲームの間互いにチャットができ、敵を作るAIを作成するときに、その会話を利用したいと思っている。AIの機能には、与えられたフレーズがプレーヤーのチャットの一部であるか判断するということが含まれている。もちろん、さまざまなフレーズが与えられるのだが、できるだけそれを見つけ出したいと思っている。フレーズに使われるのは、簡略表記が最も一般的であろう。例えば、cptrというのはcaptureという言葉の略である。さて、問題ではtypedというプレーヤーがタイプした文字列と、それに対しチェックしたいphraseという文字列が与えられる。phraseからtypedの文字を取り除いた結果を返せ。もし、phraseからtypedを単に除いた文字列が得られないようであれば、"UNMATCHED"を返せ。なお、この制約により、返す文字列は唯一に定まる。
私の解答はこちら。
public class ListeningIn {
public String probableMatch(String typed, String phrase) {
StringBuilder sb = new StringBuilder();
int nStart = 0;
int nPrev = 0;
for( int i=0 ; i<typed.length() ; i++ ){
String aTyped = typed.substring(i, i+1);
if( nPrev > phrase.length()-1 ){
// まだ検討しなければならない文字が残っているのに、終端まで来てしまった
return "UNMATCHED";
}
for( int j=nStart ; j<phrase.length() ; j++ ){ // 直前の文字の次からスタート
if( phrase.substring(j, j+1).equals(aTyped) ){ // 探したい文字があった
nStart = j+1; // 次の開始位置
break;
}
}
if( nPrev == nStart ) return "UNMATCHED"; // 次の開始位置が見つからなかった
// typedに現れた2文字の間を解答を格納する変数に入れる
sb.append(phrase.substring(nPrev, nStart-1));
nPrev = nStart; // 次の開始位置は直前の開始位置になる
}
sb.append(phrase.substring(nPrev));
String ret = sb.toString();
return ret;
}
}typedの先頭から順に何番目の文字と一致するかということを調べて、次の文字からは先頭の位置から順に後方に現れ、phraseの一番後ろに行くまでにtypedがすべて現れればOKというのが方針。実装するに当たり、空白は飛ばすなど要求と異なる実装をしていたので、かなり時間がかかってしまいました。

0 件のコメント:
コメントを投稿