どんどん行きます。
http://ttpc2015.contest.atcoder.jp/tasks/ttpc2015_g
問題
文字列Sを(非連続でもよい)いくつかの部分文字列に分解する。
各部分文字列が"titech"となるようにできるか判定せよ。
解法
titechと1文字一致するごとに以下のように遷移するオートマトンを考える。
(開始)→1→2→3→4→5→6(ゴール)
入力がL文字とすると、上記オートマトンがL/6個あり、1文字ごとでどれか1個のオートマトンを1個状態遷移すると考える。
あとは各状態のオートマトンが何個あるか、を状態としてDFSしていくとよい。
全オートマトンが終了状態に遷移してたら条件を満たす。
なお、想定解法では同じオートマトンにしてももう少し軽い(tで分岐の生じない)方法をとってO(L)で終わるようにしているようだ。
char did[17][17][17][17][17][17]; int L; string S; void dfs(int cur,vector<int>& v) { if(cur==L) { if(v[0]+v[1]+v[2]+v[3]+v[4]+v[5]) return; _P("Yes\n"); exit(0); } if(did[v[0]][v[1]][v[2]][v[3]][v[4]][v[5]]) return; did[v[0]][v[1]][v[2]][v[3]][v[4]][v[5]] = 1; int i; if(S[cur]=='t') { i=0; if(v[i]&&v[i+1]<L/6) v[i]--, v[i+1]++, dfs(cur+1,v), v[i]++, v[i+1]--; i=2; if(v[i]&&v[i+1]<L/6) v[i]--, v[i+1]++, dfs(cur+1,v), v[i]++, v[i+1]--; } else if(S[cur]=='i') { i=1; if(v[i]&&v[i+1]<L/6) v[i]--, v[i+1]++, dfs(cur+1,v), v[i]++, v[i+1]--; } else if(S[cur]=='e') { i=3; if(v[i]&&v[i+1]<L/6) v[i]--, v[i+1]++, dfs(cur+1,v), v[i]++, v[i+1]--; } else if(S[cur]=='c') { i=4; if(v[i]&&v[i+1]<L/6) v[i]--, v[i+1]++, dfs(cur+1,v), v[i]++, v[i+1]--; } else if(S[cur]=='h') { i=5; if(v[i]) v[i]--, dfs(cur+1,v), v[i]++; } else { _P("No\n"); exit(0); } } void solve() { int i,j,k,l,r,x,y; string s; cin>>S; L=S.size(); if(L%6) return _P("No\n"); vector<int> v(6,0); v[0]=L/6; dfs(0,v); _P("No\n"); }
まとめ
正規表現とかでさらっと書けたりしないのかな?