Problem:
全宇宙生命ゲノムデータベース リターンズ

西暦2301年，宇宙連邦共和国の生命科学局では，宇宙生物のゲノム配列の研究を行っていた．近年の研究の結果，ゲノム配列に特定のパターンが何回現れるかが生物の性質に大きく影響することが分かってきた．

宇宙生物のゲノム配列は英大文字からなる文字列で表される．研究員たちはゲノム配列の中に，ある特定のパターンが何回現れるかを数え上げることにした．しかしながら，宇宙生物のゲノム配列は非常に長いため，後述する方法で繰り返しがある部分文字列を圧縮してデータベースに保存している．

あなたの仕事は圧縮されたゲノム配列 S から文字列 Q の出現回数を数え上げるプログラムを作成することである．ただし，Q の出現は，開始位置さえ異なっていれば，重なっている部分があっても別の出現として数える．例えば， MISSISSIPPI に ISSI は 2 回出現する．

ゲノム配列の圧縮方法は以下のBNFで定義される．

<Genome> ::= <Letter> | <Number> <Letter> | <Number> ( <Genome> ) | <Genome> <Genome>
<Letter> ::= 'A' | 'B' | … | 'Z'
<Number> ::= <Digit> | <Number> '0' | <Number> <Digit>
<Digit> ::= '1' | '2' | … | '9'

ここで，文字列の前に付けられる整数はその文字列がその回数だけ繰り返されることを表す．例えば，5A は AAAAA を表し，2(AB) は ABAB を表す．整数の直後に括弧がない場合は，その直後の1文字のみが繰り返される．例えば，2AB は AAB を表す．繰り返しは多重にネストすることが可能で，2(2(AB)C) は 2(ABABC) と同じであり，ABABCABABC を表す．

Input

入力は最大で 50 個のデータセットから構成される．各データセットは次の形式で表される．

S
Q

各データセットの1行目は，圧縮されたゲノム配列を表す文字列 S である．S は上記のBNFに従い，その長さは 1 以上 3 000 文字以下である．また，S を展開した元のゲノム配列の長さは 1018 以下である．各データセットの2行目は数え上げる対象となる文字列 Q である．Q は英大文字からなり，長さは 1 以上 3 000 文字以下である．

入力の終了は '#' の1文字だけを含む行で表される．

Output

各データセットについて，S を展開した文字列に Q が何回現れるかを出力せよ．

Sample Input

MI2(2SI)2PI
ISSI
100(100(JAG))
JAG
1000000000000000000A
AAAAA
#

Output for the Sample Input

2
10000
999999999999999996

Solution in Scala (judge verdict: Accepted)

import scala.annotation.tailrec
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
import scala.io.StdIn._

object Main extends App {
  solve()
  @tailrec def solve(): Unit = {
    val s = readLine.trim
    if (s == "#") return
    val q = readLine.trim
    s match {
      case Genome(g) ⇒ println(g.countPattern(q))
      case _ ⇒ ???
    }
    solve()
  }

  trait Genome {
    def countPattern(pattern: String): Long = {
      val automaton = Automaton(pattern)
      val defaultNext = ('A' to 'Z').map{c ⇒ automaton.map{_.move(c).id}}.toArray
      val defaultCount = Array.tabulate(26){c ⇒ Array.tabulate(automaton.length){i ⇒ if (defaultNext(c)(i) == pattern.length) 1L else 0L}}
      val matcher = makeMatcher(defaultNext, defaultCount)
      matcher.matchCount
    }
    protected def makeMatcher(defaultNext: Array[Array[Int]], defaultCount: Array[Array[Long]]): PatternMatcher
  }
  object Genome {
    def unapply(arg: String): Option[Genome] = {
      arg.toList match {
        case g SeqGenome Nil ⇒ Some(g)
        case _ ⇒ None
      }
    }
    private object SingleGenome {
      def unapply(arg: List[Char]): Option[(SingleGenome, List[Char])] = {
        arg match {
          case h::t if h.isUpper ⇒ Some(new SingleGenome(h), t)
          case _ ⇒ None
        }
      }
    }
    private class SingleGenome(char: Char) extends Genome {
      override protected def makeMatcher(defaultNext: Array[Array[Int]], defaultCount: Array[Array[Long]]): PatternMatcher = {
        new PatternMatcher(defaultNext(char - 'A'), defaultCount(char - 'A'))
      }
    }
    private object SeqGenome {
      def unapply(arg: List[Char]): Option[(SeqGenome, List[Char])] = {
        arg match {
          case g SingleGenome t ⇒ Some(takeAll(t, List(g)))
          case g RepeatGenome t ⇒ Some(takeAll(t, List(g)))
          case _ ⇒ None
        }
      }
      @tailrec private[this] def takeAll(arg: List[Char], genomes: List[Genome]): (SeqGenome, List[Char]) = {
        arg match {
          case g SingleGenome t ⇒ takeAll(t, g::genomes)
          case g RepeatGenome t ⇒ takeAll(t, g::genomes)
          case _ ⇒ (new SeqGenome(genomes.reverse), arg)
        }
      }
    }
    private class SeqGenome(genoms: List[Genome]) extends Genome {
      override protected def makeMatcher(defaultNext: Array[Array[Int]], defaultCount: Array[Array[Long]]): PatternMatcher = {
        genoms.map{_.makeMatcher(defaultNext, defaultCount)}.reduce(_ + _)
      }
    }
    private object RepeatGenome {
      def unapply(arg: List[Char]): Option[(RepeatGenome, List[Char])] = {
        arg match {
          case n Number '('::(g SeqGenome ')'::t) ⇒ Some(new RepeatGenome(g, n), t)
          case n Number (g SingleGenome t) ⇒ Some(new RepeatGenome(g, n), t)
          case _ ⇒ None
        }
      }
    }
    private class RepeatGenome(genome: Genome, times: Long) extends Genome {
      override protected def makeMatcher(defaultNext: Array[Array[Int]], defaultCount: Array[Array[Long]]): PatternMatcher = genome.makeMatcher(defaultNext, defaultCount).repeat(times)
    }
    private object Number {
      def unapply(arg: List[Char]): Option[(Long, List[Char])] = {
        arg.span(_.isDigit) match {
          case (Nil, _) ⇒ None
          case (n, t) ⇒ Some(n.foldLeft(0L){case (acc, c) ⇒ acc * 10 + c.asDigit}, t)
        }
      }
    }
  }

  class PatternMatcher(val next: Array[Int], val count: Array[Long]) {
    def matchCount: Long = count.head
    def +(that: PatternMatcher): PatternMatcher = {
      val newNext = Array.tabulate(next.length){i ⇒ that.next(next(i))}
      val newCount = Array.tabulate(count.length){i ⇒ count(i) + that.count(next(i))}
      new PatternMatcher(newNext, newCount)
    }
    def repeat(times: Long): PatternMatcher = {
      times match {
        case 1L ⇒ this
        case _ if times % 2 == 0 ⇒ (this + this).repeat(times / 2)
        case _ ⇒ (this + this).repeat(times / 2) + this
      }
    }
  }
  trait Automaton {
    def move(char: Char): Automaton
    def id: Int
    def isMatch: Boolean
  }
  object Automaton {
    def apply(word: String): Array[Automaton] = {
      val result = ArrayBuffer[AutomatonImpl](new RootImpl)
      for ((c, i) ← word.zipWithIndex) {
        result.append(new ChildImpl(result.last.move(c), i + 1, i == word.length - 1))
        result(i).nextStates += c → result.last
      }
      result.toArray
    }
    private trait AutomatonImpl extends Automaton {
      val nextStates: mutable.Map[Char, Automaton]
    }
    private class RootImpl extends AutomatonImpl {
      override val nextStates = mutable.Map[Char, Automaton]()
      override def move(char: Char): Automaton = nextStates.getOrElseUpdate(char, this)
      override def id: Int = 0
      override def isMatch: Boolean = false
    }
    private class ChildImpl(failure: Automaton, override val id: Int, override val isMatch: Boolean) extends AutomatonImpl {
      override val nextStates = mutable.Map[Char, Automaton]()
      override def move(char: Char): Automaton = nextStates.getOrElseUpdate(char, failure.move(char))
    }
  }
}