AtCoderのABC
次のABCの問題へ
前のABCの問題へ
ABC324-E Joint Two Strings
C#のソース
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("3 bac");
WillReturn.Add("abba");
WillReturn.Add("bcb");
WillReturn.Add("aaca");
//3
}
else if (InputPattern == "Input2") {
WillReturn.Add("5 xx");
WillReturn.Add("x");
WillReturn.Add("x");
WillReturn.Add("x");
WillReturn.Add("x");
WillReturn.Add("x");
//25
}
else if (InputPattern == "Input3") {
WillReturn.Add("1 y");
WillReturn.Add("x");
//0
}
else if (InputPattern == "Input4") {
WillReturn.Add("10 ms");
WillReturn.Add("mkgn");
WillReturn.Add("m");
WillReturn.Add("hlms");
WillReturn.Add("vmsle");
WillReturn.Add("mxsm");
WillReturn.Add("nnzdhi");
WillReturn.Add("umsavxlb");
WillReturn.Add("ffnsybomr");
WillReturn.Add("yvmm");
WillReturn.Add("naouel");
//68
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static string mT;
struct StrInfoDef
{
internal int StaMatchCnt; // 先頭からの一致数
internal int EndMatchCnt; // 末尾からの一致数
}
static List<StrInfoDef> mStrInfoList = new List<StrInfoDef>();
static void Main()
{
List<string> InputList = GetInputList();
string[] SplitArr = InputList[0].Split(' ');
mT = SplitArr[1];
foreach (string EachStr in InputList.Skip(1)) {
StrInfoDef WillAdd;
WillAdd.StaMatchCnt = DeriveStaMatchCnt(EachStr);
WillAdd.EndMatchCnt = DeriveEndMatchCnt(EachStr);
mStrInfoList.Add(WillAdd);
//Console.WriteLine("{0}のStaMatchCnt={1},EndMatchCnt={2}",
// EachStr, WillAdd.StaMatchCnt, WillAdd.EndMatchCnt);
}
var ValList1 = new List<long>();
var ValList2 = new List<long>();
foreach (StrInfoDef EachStrInfo in mStrInfoList) {
ValList1.Add(EachStrInfo.StaMatchCnt);
ValList2.Add(EachStrInfo.EndMatchCnt);
}
ValList2.Sort();
long Answer = 0;
foreach (long EachInt in ValList1) {
long RestCnt = mT.Length - EachInt;
long ResultInd = ExecNibunhou_LowerBound(RestCnt, ValList2);
if (ResultInd == -1) continue;
long UB = ValList2.Count - 1;
Answer += UB - ResultInd + 1;
}
Console.WriteLine(Answer);
}
// 先頭からの一致数を返す
static int DeriveStaMatchCnt(string CurrStr)
{
int MatchCnt = 0;
int UB1 = mT.Length - 1;
int UB2 = CurrStr.Length - 1;
int Ind1 = 0;
int Ind2 = 0;
while (Ind1 <= UB1 && Ind2 <= UB2) {
if (mT[Ind1] == CurrStr[Ind2]) {
Ind1++; Ind2++;
MatchCnt++;
}
else {
Ind2++;
}
}
return MatchCnt;
}
// 末尾からの一致数を返す
static int DeriveEndMatchCnt(string CurrStr)
{
int MatchCnt = 0;
int Ind1 = mT.Length - 1;
int Ind2 = CurrStr.Length - 1;
while (0 <= Ind1 && 0 <= Ind2) {
if (mT[Ind1] == CurrStr[Ind2]) {
Ind1--; Ind2--;
MatchCnt++;
}
else {
Ind2--;
}
}
return MatchCnt;
}
// 二分法で、Val以上で最小の値を持つ、添字を返す
static int ExecNibunhou_LowerBound(long pVal, List<long> pList)
{
// 最後の要素がVal未満の特殊ケース
if (pVal > pList.Last()) {
return -1;
}
// 最初の要素がVal以上の特殊ケース
if (pVal <= pList[0]) {
return 0;
}
int L = 0;
int R = pList.Count - 1;
while (L + 1 < R) {
int Mid = (L + R) / 2;
if (pList[Mid] >= pVal) {
R = Mid;
}
else {
L = Mid;
}
}
return R;
}
}
解説
前処理で
先頭からの一致数と
末尾からの一致数を求めます。
それから、二分探索すれば答えを求めることができます。