Submission #68303401
Source Code Expand
// Go 1.20.6
// 二重ローリングハッシュによる高速回文判定
// 実行方法: go run main.go < input.txt
package main
import (
"bufio"
"fmt"
"os"
"runtime"
"time"
)
// buildHash は文字列 S に対して基数 base と法 mod を用いた
// 累乗配列、正方向ハッシュ配列、逆方向ハッシュ配列を構築する
//
// Parameters:
// S string : 対象文字列(英小文字)
// base int64 : ローリングハッシュの基数
// mod int64 : 法(素数)
//
// Returns:
// pow []int64 : base^i % mod の累乗配列
// hf []int64 : 正方向 prefix hash 配列(1-indexed)
// hr []int64 : 逆方向 prefix hash 配列(1-indexed)
func buildHash(S string, base, mod int64) ([]int64, []int64, []int64) {
n := len(S)
pow := make([]int64, n+1)
hf := make([]int64, n+1)
hr := make([]int64, n+1)
pow[0] = 1
for i := 1; i <= n; i++ {
pow[i] = (pow[i-1] * base) % mod
}
for i := 0; i < n; i++ {
val := int64(S[i]-'a'+1)
hf[i+1] = (hf[i]*base + val) % mod
}
for i := 0; i < n; i++ {
val := int64(S[n-1-i]-'a'+1)
hr[i+1] = (hr[i]*base + val) % mod
}
return pow, hf, hr
}
// getSubHash は prefix hash 配列から部分文字列 [l, r] (1-indexed) のハッシュ値を取得する
//
// Parameters:
// hf []int64 : prefix hash 配列(1-indexed)
// pow []int64 : base^i % mod の累乗配列
// l int : 部分文字列の開始位置 (1-indexed)
// r int : 部分文字列の終了位置 (1-indexed)
// mod int64 : 法
//
// Returns:
// hashValue int64 : 部分文字列のハッシュ値
func getSubHash(hf, pow []int64, l, r int, mod int64) int64 {
length := r - l + 1
res := hf[r] - (hf[l-1]*pow[length])%mod
res %= mod
if res < 0 {
res += mod
}
return res
}
// solve は N, Q, S, クエリ配列を受け取り回文判定結果を返す
//
// Parameters:
// N int : 文字列長
// Q int : クエリ数
// S string : 対象文字列
// queries [][2]int : 各クエリ (L, R) の配列
//
// Returns:
// results []string : 各クエリに対する "Yes" または "No" の結果
func solve(N, Q int, S string, queries [][2]int) []string {
const MOD1 int64 = 1000000007
const MOD2 int64 = 1000000009
const BASE1 int64 = 1000003
const BASE2 int64 = 1000033
pow1, hf1, hr1 := buildHash(S, BASE1, MOD1)
pow2, hf2, hr2 := buildHash(S, BASE2, MOD2)
results := make([]string, Q)
for i, q := range queries {
L, R := q[0], q[1]
fh1 := getSubHash(hf1, pow1, L, R, MOD1)
fh2 := getSubHash(hf2, pow2, L, R, MOD2)
revL := N - R + 1
revR := N - L + 1
rh1 := getSubHash(hr1, pow1, revL, revR, MOD1)
rh2 := getSubHash(hr2, pow2, revL, revR, MOD2)
if fh1 == rh1 && fh2 == rh2 {
results[i] = "Yes"
} else {
results[i] = "No"
}
}
return results
}
func main() {
in := bufio.NewReaderSize(os.Stdin, 1<<20)
out := bufio.NewWriterSize(os.Stdout, 1<<20)
defer out.Flush()
var N, Q int
fmt.Fscan(in, &N, &Q)
var S string
fmt.Fscan(in, &S)
queries := make([][2]int, Q)
for i := 0; i < Q; i++ {
fmt.Fscan(in, &queries[i][0], &queries[i][1])
}
start := time.Now()
results := solve(N, Q, S, queries)
elapsed := time.Since(start)
for _, res := range results {
fmt.Fprintln(out, res)
}
// メモリ使用量計測
var m runtime.MemStats
runtime.ReadMemStats(&m)
fmt.Fprintf(os.Stderr, "Time: %v ms\n", elapsed.Milliseconds())
fmt.Fprintf(os.Stderr, "Memory: %.2f MB\n", float64(m.Alloc)/1024.0/1024.0)
}
Submission Info
| Submission Time |
|
| Task |
B56 - Palindrome Queries |
| User |
myoshizumi |
| Language |
Go (go 1.20.6) |
| Score |
1000 |
| Code Size |
3693 Byte |
| Status |
AC |
| Exec Time |
81 ms |
| Memory |
12116 KiB |
Judge Result
| Set Name |
Sample |
All |
| Score / Max Score |
0 / 0 |
1000 / 1000 |
| Status |
|
|
| Set Name |
Test Cases |
| Sample |
sample_01.txt |
| All |
killer_01.txt, killer_02.txt, killer_03.txt, max_01.txt, max_02.txt, max_03.txt, max_04.txt, max_05.txt, min_01.txt, random_01.txt, random_02.txt, random_03.txt, random_04.txt, random_05.txt, random_06.txt, sample_01.txt |
| Case Name |
Status |
Exec Time |
Memory |
| killer_01.txt |
AC |
73 ms |
8900 KiB |
| killer_02.txt |
AC |
66 ms |
8820 KiB |
| killer_03.txt |
AC |
65 ms |
10708 KiB |
| max_01.txt |
AC |
59 ms |
12116 KiB |
| max_02.txt |
AC |
64 ms |
12036 KiB |
| max_03.txt |
AC |
69 ms |
12112 KiB |
| max_04.txt |
AC |
69 ms |
12016 KiB |
| max_05.txt |
AC |
78 ms |
12064 KiB |
| min_01.txt |
AC |
1 ms |
1864 KiB |
| random_01.txt |
AC |
81 ms |
12008 KiB |
| random_02.txt |
AC |
81 ms |
12008 KiB |
| random_03.txt |
AC |
81 ms |
12012 KiB |
| random_04.txt |
AC |
80 ms |
12020 KiB |
| random_05.txt |
AC |
80 ms |
12032 KiB |
| random_06.txt |
AC |
80 ms |
12036 KiB |
| sample_01.txt |
AC |
1 ms |
1872 KiB |