トップページに戻る
次の競技プログラミングの問題へ
前の競技プログラミングの問題へ
東工大プロコン2015 G titech分離
■■■問題■■■
英小文字(a-z)からなる文字列Sが与えられる。
Sをいくつかの(連続とは限らない)部分文字列に分解する。
つまり、Sの各文字がちょうど1つの部分文字列に含まれるように、Sから複数の部分文字列を選ぶ。
分解した結果の部分文字列が全てtitechになるような分解方法があるかどうか判定せよ。
■■■入力■■■
S
1行目に文字列S(1 <= |S| <= 100)が与えられる。
■■■出力■■■
分解が可能ならYes、不可能ならNoを出力せよ。出力の末尾に改行を入れること。
C#のソース
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static string InputPattern = "Input1";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
if (InputPattern == "Input1") {
WillReturn.Add("titech");
//Yes
//1つのtitechに分解できる
}
else if (InputPattern == "Input2") {
WillReturn.Add("tititechtech");
//Yes
//例えば、1,2,5,6,7,8文字目と3,4,9,10,11,12文字目に分解すれば2つのtitechに分解できる
}
else if (InputPattern == "Input3") {
WillReturn.Add("titecg");
//No
}
else if (InputPattern == "Input4") {
WillReturn.Add("tttiiittteeeccchhh");
//Yes
//3つのtitechに分解できる
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static void Main()
{
List<string> InputList = GetInputList();
Console.WriteLine(Solve(InputList[0]));
}
static string Solve(string pTarget)
{
//余計な文字の有無をチェック
int CntT = pTarget.Count(X => X == 't');
int CntI = pTarget.Count(X => X == 'i');
int CntE = pTarget.Count(X => X == 'e');
int CntC = pTarget.Count(X => X == 'c');
int CntH = pTarget.Count(X => X == 'h');
if (pTarget.Length != CntT + CntI + CntE + CntC + CntH) return "No";
if (CntT != CntI * 2) return "No";
if (CntT != CntC * 2) return "No";
if (CntT != CntE * 2) return "No";
if (CntT != CntH * 2) return "No";
int AutoMatonCnt = CntT / 2;
int[] AutoMatonArr = new int[AutoMatonCnt];
for (int I = 0; I <= AutoMatonArr.GetUpperBound(0); I++) {
AutoMatonArr[I] = -1;
}
Action<int> wkAct = pCurrJyoutai =>
{
//最後のtは、次にt待ちのeがないとき限定で受理
if (pCurrJyoutai == 4) {
if (AutoMatonArr.Contains(2))
return;
}
int wkInd = Array.IndexOf(AutoMatonArr, pCurrJyoutai);
if (wkInd < 0) return;
AutoMatonArr[wkInd]++;
};
//オートマトンは-1が初期状態で
//下記の状態番号に遷移する
//hcetit
//012345
for (int I = pTarget.Length - 1; 0 <= I; I--) {
char CurrStr = pTarget[I];
if (CurrStr == 'h') wkAct(-1);
if (CurrStr == 'c') wkAct(0);
if (CurrStr == 'e') wkAct(1);
if (CurrStr == 't') wkAct(2);
if (CurrStr == 'i') wkAct(3);
if (CurrStr == 't') wkAct(4);
}
return Array.TrueForAll(AutoMatonArr, X => X == 5) ? "Yes" : "No";
}
}
解説
titechを受理するオートマトンを何個か用意して
正順に文字列を見ていくと、バックトラックが必要だと思いますが、
hcetitを受理するオートマトンを何個か用意して
逆順に文字列を見ていくと、貪欲法が使えます。
(最後のtは、次にt待ちのeがないとき限定で受理とできるため)