using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static string InputPattern = "InputX";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
if (InputPattern == "Input1") {
WillReturn.Add("aabbaa");
//4
}
else if (InputPattern == "Input2") {
WillReturn.Add("aaaccacabaababc");
//12
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static void Main()
{
List<string> InputList = GetInputList();
string S = InputList[0];
int UB = S.Length - 1;
// 最小の分割数[現在添字,前回文字列の長さ] なDP表
int?[,] DPArr = new int?[UB + 1, 3 + 1];
DPArr[0, 0] = 0;
int Answer = int.MinValue;
for (int I = 0; I <= UB; I++) {
for (int J = 0; J <= 3; J++) {
if (DPArr[I, J].HasValue == false) continue;
var sb = new System.Text.StringBuilder();
for (int K = I - J; K <= I - 1; K++) {
if (K >= 0) {
sb.Append(S[K]);
}
}
string PrevStr = sb.ToString();
sb.Length = 0;
for (int K = 1; K <= 3; K++) {
int NewVal = DPArr[I, J].Value + 1;
int CurrInd = I + K - 1;
if (CurrInd > UB) {
break;
}
sb.Append(S[CurrInd]);
string CurrStr = sb.ToString();
if (PrevStr == CurrStr) continue;
if (CurrInd == UB) {
Answer = Math.Max(Answer, NewVal);
break;
}
int NewI = CurrInd + 1;
int NewJ = CurrStr.Length;
if (NewI <= UB) {
if (DPArr[NewI, NewJ].HasValue) {
if (DPArr[NewI, NewJ].Value >= NewVal) {
continue;
}
}
DPArr[NewI, NewJ] = NewVal;
}
}
}
}
Console.WriteLine(Answer);
}
}
左の文字数が1で、右の文字数が1の場合
左の文字数が1で、右の文字数が2の場合
左の文字数が1で、右の文字数が3の場合
左の文字数が2で、右の文字数が1の場合
左の文字数が2で、右の文字数が2の場合
左の文字数が2で、右の文字数が3の場合
左の文字数が3で、右の文字数が1の場合
左の文字数が3で、右の文字数が2の場合
左の文字数が3で、右の文字数が3の場合
と考えると
最大でも3文字あれば
左の文字数が1で、右の文字数が1の場合 → 1,3,1
左の文字数が1で、右の文字数が2の場合 → 1,2,1,2
左の文字数が1で、右の文字数が3の場合 → 1,2,1,3
左の文字数が2で、右の文字数が1の場合 → 2,1,2,1
左の文字数が2で、右の文字数が2の場合 → 2,3,2
左の文字数が2で、右の文字数が3の場合 → 2,1,2,3
左の文字数が3で、右の文字数が1の場合 → 3,1,2,1
左の文字数が3で、右の文字数が2の場合 → 3,2,1,2
左の文字数が3で、右の文字数が3の場合 → 3,1,2,3
として、文字数を違う状態にできるので
最適解の各分割は、最大でも3文字だと分かります。
後は、
最小の分割数[現在添字,前回文字列の長さ]
を更新するDPで解けます。