← Home
For problem statement at 1000-1999/1300-1399/1390-1399/1393/problemE1.txt this is a correct solution, but verifier at 1000-1999/1300-1399/1390-1399/1393/verifierE1.go ends with Test 1 failed
input:
2
ca
cbcbb
expected: 16 got: 13

exit status 1 can you fix the verifier? package main

import (
	"bufio"
	"fmt"
	"os"
	"sort"
)

const MOD = 1000000007

var (
	n       int
	words   []string
	lens    []int
	starts  []int
	concat  []byte
	rankPos []int
	lg      []int
	st      [][]int
)

func buildSuffixArray(s []byte) ([]int, []int, []int) {
	m := len(s)
	sa := make([]int, m)
	rank := make([]int, m)
	tmp := make([]int, m)
	for i := 0; i < m; i++ {
		sa[i] = i
		rank[i] = int(s[i])
	}
	for k := 1; ; k <<= 1 {
		sort.Slice(sa, func(i, j int) bool {
			a, b := sa[i], sa[j]
			if rank[a] != rank[b] {
				return rank[a] < rank[b]
			}
			ra, rb := -1, -1
			if a+k < m {
				ra = rank[a+k]
			}
			if b+k < m {
				rb = rank[b+k]
			}
			return ra < rb
		})
		tmp[sa[0]] = 0
		cls := 0
		for i := 1; i < m; i++ {
			a, b := sa[i-1], sa[i]
			a1, b1 := rank[a], rank[b]
			a2, b2 := -1, -1
			if a+k < m {
				a2 = rank[a+k]
			}
			if b+k < m {
				b2 = rank[b+k]
			}
			if a1 != b1 || a2 != b2 {
				cls++
			}
			tmp[b] = cls
		}
		copy(rank, tmp)
		if cls == m-1 {
			break
		}
	}
	pos := make([]int, m)
	for i, p := range sa {
		pos[p] = i
	}
	lcp := make([]int, m)
	k := 0
	for i := 0; i < m; i++ {
		r := pos[i]
		if r == 0 {
			k = 0
			continue
		}
		j := sa[r-1]
		for i+k < m && j+k < m && s[i+k] == s[j+k] {
			k++
		}
		lcp[r] = k
		if k > 0 {
			k--
		}
	}
	return sa, pos, lcp
}

func buildRMQ(lcp []int) {
	m := len(lcp)
	lg = make([]int, m+1)
	for i := 2; i <= m; i++ {
		lg[i] = lg[i/2] + 1
	}
	kmax := lg[m] + 1
	st = make([][]int, kmax)
	st[0] = make([]int, m)
	copy(st[0], lcp)
	for k := 1; k < kmax; k++ {
		length := 1 << k
		half := 1 << (k - 1)
		st[k] = make([]int, m-length+1)
		for i := 0; i+length <= m; i++ {
			a := st[k-1][i]
			b := st[k-1][i+half]
			if a < b {
				st[k][i] = a
			} else {
				st[k][i] = b
			}
		}
	}
}

func lcpPos(p, q int) int {
	if p == q {
		return len(concat) - p
	}
	rp, rq := rankPos[p], rankPos[q]
	if rp > rq {
		rp, rq = rq, rp
	}
	l := rp + 1
	r := rq
	j := lg[r-l+1]
	a := st[j][l]
	b := st[j][r-(1<<j)+1]
	if a < b {
		return a
	}
	return b
}

func lcpWord(wi, a, wj, b int) int {
	if a >= lens[wi] || b >= lens[wj] {
		return 0
	}
	p := starts[wi] + a
	q := starts[wj] + b
	res := lcpPos(p, q)
	rem1 := lens[wi] - a
	rem2 := lens[wj] - b
	if res > rem1 {
		res = rem1
	}
	if res > rem2 {
		res = rem2
	}
	return res
}

func candLen(w, del int) int {
	if del < lens[w] {
		return lens[w] - 1
	}
	return lens[w]
}

func charAt(w, del, k int) byte {
	if del == lens[w] || k < del {
		return words[w][k]
	}
	return words[w][k+1]
}

func lcpCand(wi, di, wj, dj int) int {
	m := lens[wi]
	n := lens[wj]
	dx := 0
	if di < m {
		dx = 1
	}
	dy := 0
	if dj < n {
		dy = 1
	}
	lx := m - dx
	ly := n - dy

	r := di
	if dj < r {
		r = dj
	}
	l0 := lcpWord(wi, 0, wj, 0)
	if l0 > r {
		l0 = r
	}
	if l0 < r {
		return l0
	}

	if di == dj {
		remx := lx - di
		remy := ly - dj
		if remx <= 0 || remy <= 0 {
			return di
		}
		l1 := lcpWord(wi, di+dx, wj, dj+dy)
		if l1 > remx {
			l1 = remx
		}
		if l1 > remy {
			l1 = remy
		}
		return di + l1
	}

	if di < dj {
		phase := dj - di
		l2 := lcpWord(wi, di+dx, wj, di)
		if l2 > phase {
			l2 = phase
		}
		if l2 < phase {
			return di + l2
		}
		remx := lx - dj
		remy := ly - dj
		if remx <= 0 || remy <= 0 {
			return dj
		}
		l3 := lcpWord(wi, dj+dx, wj, dj+dy)
		if l3 > remx {
			l3 = remx
		}
		if l3 > remy {
			l3 = remy
		}
		return dj + l3
	}

	phase := di - dj
	l2 := lcpWord(wi, dj, wj, dj+dy)
	if l2 > phase {
		l2 = phase
	}
	if l2 < phase {
		return dj + l2
	}
	remx := lx - di
	remy := ly - di
	if remx <= 0 || remy <= 0 {
		return di
	}
	l3 := lcpWord(wi, di+dx, wj, di+dy)
	if l3 > remx {
		l3 = remx
	}
	if l3 > remy {
		l3 = remy
	}
	return di + l3
}

func cmpCand(wi, di, wj, dj int) int {
	la := candLen(wi, di)
	lb := candLen(wj, dj)
	l := lcpCand(wi, di, wj, dj)
	minlen := la
	if lb < minlen {
		minlen = lb
	}
	if l > minlen {
		l = minlen
	}
	if l == minlen {
		if la < lb {
			return -1
		}
		if la > lb {
			return 1
		}
		return 0
	}
	a := charAt(wi, di, l)
	b := charAt(wj, dj, l)
	if a < b {
		return -1
	}
	return 1
}

func main() {
	in := bufio.NewReaderSize(os.Stdin, 1<<20)
	out := bufio.NewWriterSize(os.Stdout, 1<<20)
	defer out.Flush()

	fmt.Fscan(in, &n)
	words = make([]string, n)
	lens = make([]int, n)
	starts = make([]int, n)

	for i := 0; i < n; i++ {
		fmt.Fscan(in, &words[i])
		lens[i] = len(words[i])
	}

	for i := 0; i < n; i++ {
		starts[i] = len(concat)
		concat = append(concat, words[i]...)
		concat = append(concat, '{')
	}

	var lcp []int
	_, rankPos, lcp = buildSuffixArray(concat)
	buildRMQ(lcp)

	cands := make([][]int, n)
	for i := 0; i < n; i++ {
		m := lens[i]
		ds := make([]int, m+1)
		for j := 0; j < m; j++ {
			ds[j] = j
		}
		ds[m] = m
		sort.Slice(ds, func(a, b int) bool {
			return cmpCand(i, ds[a], i, ds[b]) < 0
		})
		uniq := ds[:0]
		for _, d := range ds {
			if len(uniq) == 0 || cmpCand(i, uniq[len(uniq)-1], i, d) != 0 {
				uniq = append(uniq, d)
			}
		}
		tmp := make([]int, len(uniq))
		copy(tmp, uniq)
		cands[i] = tmp
	}

	dp := make([]int, len(cands[0]))
	for i := range dp {
		dp[i] = 1
	}

	for i := 1; i < n; i++ {
		prev := cands[i-1]
		cur := cands[i]
		ndp := make([]int, len(cur))
		sum := 0
		j := 0
		for idx, d := range cur {
			for j < len(prev) && cmpCand(i-1, prev[j], i, d) <= 0 {
				sum += dp[j]
				if sum >= MOD {
					sum -= MOD
				}
				j++
			}
			ndp[idx] = sum
		}
		dp = ndp
	}

	ans := 0
	for _, v := range dp {
		ans += v
		if ans >= MOD {
			ans -= MOD
		}
	}
	fmt.Fprintln(out, ans)
}