Problem:
IOIOI

問題

整数 n (1 ≤ n) に対し, n + 1 個の I と n 個の O を I から始めて交互に並べてできる文字列を Pn とする.ここで I と O はそれぞれ英大文字のアイとオーである.

P1

IOI

P2

IOIOI

P3

IOIOIOI

.

.

.

Pn

IOIOIO ... OI (O が n 個)

図 1-1 本問で考える文字列 Pn

整数 n と, I と O のみからなる文字列 s が与えられた時, s の中に Pn が何ヶ所含まれているかを出力するプログラムを作成せよ.

例

n が 1, s が OOIOIOIOIIOII の場合, P1 は IOI であり,下図 1-2 に示した 4ヶ所に含まれている.よって,出力は 4 である.

OOIOIOIOIIOII

OOIOIOIOIIOII

OOIOIOIOIIOII

OOIOIOIOIIOII

図 1-2 n が 1, s が OOIOIOIOIIOII の場合の例

n が 2, s が OOIOIOIOIIOII の場合, P2 は IOIOI であり,下図 1-3 に示した 2ヶ所に含まれている.よって,出力は 2 である.

OOIOIOIOIIOII

OOIOIOIOIIOII

図 1-3 n が 2, s が OOIOIOIOIIOII の場合の例

入力

入力は複数のデータセットからなる．各データセットは以下の形式で与えられる．

1 行目には整数 n (1 ≤ n ≤ 1000000) が書かれている.

2 行目には整数 m (1 ≤ m ≤ 1000000) が書かれている. m は s の文字数を表す.

3 行目には文字列 s が書かれている. s は I と O のみからなる.

全ての採点用データで, 2n + 1 ≤ m である.採点用データのうち, 配点の 50% 分については, n ≤ 100, m ≤ 10000 を満たす.

n が 0 のとき入力の終了を示す. データセットの数は 10 を超えない．

出力

データセットごとに,文字列 s に文字列 Pn が何ヶ所含まれるかを表す 1 つの整数を1 行に出力する. s に Pn が含まれていない場合は,整数として 0 を出力せよ.

入出力例

入力例

1
13
OOIOIOIOIIOII
2
13
OOIOIOIOIIOII
0

出力例

4
2

上記問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。

Solution in Haskell (judge verdict: Accepted)

import Control.Applicative
import Control.Monad
import Control.Monad.ST
import Data.Functor
import Data.Function
import Data.Monoid
import Data.Maybe
import Data.List
import qualified Data.Foldable as Foldable
import qualified Data.Set as Set
import Data.List.Split
import Data.Bits
import Data.Char
import Data.Ix
import Data.Ratio
import Data.Ord
import Data.Tuple
import Data.Array
--import Data.Array.Unboxed
import Data.Array.IO
import Data.Array.ST
import Data.IORef
import Data.STRef
-- import System.IO.Unsafe
 
readInt = read :: String -> Int
readDouble = read :: String -> Double
getInt = readLn :: IO Int
getInts = map readInt . words <$> getLine
getDouble = readLn :: IO Double
sjoin :: (Show a) => [a] -> String
sjoin = unwords . map show
cond :: a -> a -> Bool -> a
cond t f c = if c then t else f
apply2 :: (a -> a -> b) -> [a] -> b
apply2 f [x,y] = f x y
apply3 :: (a -> a -> a -> b) -> [a] -> b
apply3 f [x,y,z] = f x y z
apply4 :: (a -> a -> a -> a -> b) -> [a] -> b
apply4 f [x,y,z,w] = f x y z w
fnBin :: (b -> c -> d) -> (a -> b) -> (a -> c) -> a -> d
fnBin op f g x = op (f x) $ g x
fnTuple :: (a -> b, a -> c) -> a -> (b, c)
fnTuple (f,g) a = (f a, g a)
replace :: (Eq a) => a -> a -> [a] -> [a]
replace x y = map (\z -> if z==x then y else z)
modifyArray :: (Ix i, MArray a e m) => a i e -> i -> (e -> e) -> m ()
modifyArray arr ix f = readArray arr ix >>= writeArray arr ix . f
-- end of templete

ioi [] = []
ioi ('O':s) = ioi s
ioi ('I':s) = ioisub 0 s
ioisub 0 [] = []
ioisub n [] = [n]
ioisub n ('O':'I':s) = ioisub (n+1) s
ioisub 0 s = ioi s
ioisub n s = n : ioi s


main = do
    n <- getInt
    when (n/=0) $ do
        m <- getInt
        s <- getLine
        print $ sum $ filter (>=1) $ map (subtract (n-1)) $ ioi s
        main