競技プログラミングの鉄則
次の問題へ
前の問題へ
B56 Palindrome Queries
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("11 3");
WillReturn.Add("mississippi");
WillReturn.Add("5 8");
WillReturn.Add("6 10");
WillReturn.Add("2 8");
//Yes
//No
//Yes
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static void Main()
{
List<string> InputList = GetInputList();
string SeiS = InputList[1];
string RevS = new string(SeiS.ToCharArray().Reverse().ToArray());
int UB = SeiS.Length - 1;
var InsRollingHashSei = new RollingHash(SeiS);
var InsRollingHashRev = new RollingHash(RevS);
int[] wkArr = { };
Action<string> SplitAct = pStr =>
wkArr = pStr.Split(' ').Select(pX => int.Parse(pX)).ToArray();
foreach (string EachStr in InputList.Skip(2)) {
SplitAct(EachStr);
int L = wkArr[0] - 1;
int R = wkArr[1] - 1;
int RevL = UB - L;
int RevR = UB - R;
decimal Hash1 = InsRollingHashSei.GetRangeHash(L, R);
decimal Hash2 = InsRollingHashRev.GetRangeHash(RevR, RevL);
if (Hash1 == Hash2) {
Console.WriteLine("Yes");
}
else {
Console.WriteLine("No");
}
}
}
}
#region RollingHash
// ローリングハッシュ
internal class RollingHash
{
const decimal Base = 100M;
const decimal Hou = 67280421310721M;
// ハッシュ値[終了Ind]で、[0,終了Ind]のハッシュ値を保持
internal decimal[] mHashArr;
// 桁の重みの配列
decimal[] mOmomiArr;
// コンストラクタ
internal RollingHash(string pTargetStr)
{
decimal Omomi = 1;
long UB = pTargetStr.Length - 1;
mHashArr = new decimal[UB + 1];
mOmomiArr = new decimal[UB + 1];
for (int I = 0; I <= UB; I++) {
mOmomiArr[I] = Omomi;
if (I > 0) {
mHashArr[I] += mHashArr[I - 1] * Base;
mHashArr[I] %= Hou;
}
mHashArr[I] += pTargetStr[I];
mHashArr[I] %= Hou;
Omomi *= Base;
Omomi %= Hou;
}
}
// [Sta,End]のハッシュ値を返す
internal decimal GetRangeHash(long pSta, long pEnd)
{
decimal WillReturn = mHashArr[pEnd];
if (pSta > 0) {
long Range = pEnd - pSta + 1;
decimal PrevVal = mHashArr[pSta - 1];
decimal MinusVal = PrevVal * mOmomiArr[Range];
MinusVal %= Hou;
WillReturn -= MinusVal;
if (WillReturn < 0) {
WillReturn += Hou;
}
}
return WillReturn;
}
}
#endregion
解説
前処理で、文字列の正順と逆順でのハッシュ値を用意してます。