概要
fmt.scanでは、大量入力時に動作が遅いという事なので、入力数$10^5$に対応する関数を書いてみました。
| バージョン | 備考 | |
|---|---|---|
| 対応バージョン | 1.6以上 |
Scanner.Buffer関数の対応バージョン |
| AtCoder | 1.6 | 2019年10月01日現在 |
| Codeforces | 1.12.6 | 2019年10月01日現在 |
基本的には、
Go 言語で標準入力から読み込む競技プログラミングのアレ --- 改訂第二版
の「bufio の Scanner を使う (2) スペース区切りで読み込む」と同じですが、改良して長大文字列をScannerで読めるようにします。
MaxScanTokenSizeの限界を突破する
デフォルトのScannerではMaxScanTokenSize=65536文字を超える文字列は読み込めなかったのですが、バージョン1.6でScanner.Buffer関数が追加されました。この関数で使用するバッファと最大読み込み文字数を変更することができます。
作成コード
import (
"os"
"bufio"
"strconv"
)
const MaxBuf = 200100
var buf []byte = make([]byte,MaxBuf)
var sc = bufio.NewScanner(os.Stdin)
func init() {
sc.Split(bufio.ScanWords)
sc.Buffer(buf,MaxBuf)
}
func readString() string {
sc.Scan()
return sc.Text()
}
func readInt() int {
sc.Scan()
r,_ := strconv.Atoi(sc.Text())
return r
}
func readInt64() int64 {
sc.Scan()
r,_ := strconv.ParseInt(sc.Text(),10,64)
return r
}
func readFloat64() float64 {
sc.Scan()
r,_ := strconv.ParseFloat(sc.Text(),64)
return r
}
func init()は、func main()の前に実行され、パッケージ変数で初期化できなかった処理を行います。
-
sc.Split(bufio.ScanWords)- 空白文字区切りで文字列を読み込むよう設定します。
-
sc.Buffer(buf,MaxBuf)- 前述の通り、読み込みバッファと最大サイズを変更します。
string型の読み込み
sc.Scan()で読み込んだ結果をそのまま返します。
int型の読み込み
n := 1と書くと、nはint型と型推論されます。int型とint64型の比較をしようとするとコンパイルエラーとなるため、整数は特に理由がない限りint型として読み込みたいです。strconv.Atoi関数を使用して文字列をint型に変換します。競技プログラミングでは入力が欠落することがないため、エラー処理は行いません。
int64型の読み込み
int型のビット数は実装によって違うことがあるため、64ビット整数であることを保証するint64型で読み込みたいことがあります。strconv.ParseInt関数を使用します。
float64型の読み込み
f := 3.14と書くと、fはfloat64型と型推論されます。float32型を使う理由は特にないため、float64型の読み込み関数のみ用意します。strconv.ParseFloat関数を使用します。