```go
package main
import (
"bufio"
"fmt"
"os"
)
type State struct {
u int8
lenW int8
is_P_longer bool
excess string
}
func main() {
reader := bufio.NewReader(os.Stdin)
var n, m int
if _, err := fmt.Fscan(reader, &n, &m); err != nil {
return
}
type Edge struct {
to int8
W string
}
adj := make([][]Edge, n+1)
for i := 0; i < m; i++ {
var u, v, k int
fmt.Fscan(reader, &u, &v, &k)
W := make([]byte, k)
for j := 0; j < k; j++ {
var w byte
fmt.Fscan(reader, &w)
W[j] = w
}
adj[u] = append(adj[u], Edge{to: int8(v), W: string(W)})
}
dp := make(map[State]int)
for u := 1; u <= n; u++ {
state := State{
u: int8(u),
lenW: 0,
is_P_longer: true,
excess: string([]byte{byte(u)}),
}
dp[state] = 1
}
MOD := 1000000007
ans := make([]int, 2*n+1)
for lenP := 1; lenP <= 2*n; lenP++ {
for state, count := range dp {
if state.lenW == int8(lenP) && state.excess == "" {
ans[lenP] = (ans[lenP] + count) % MOD
}
}
if lenP == 2*n {
break
}
next_dp := make(map[State]int)
for state, count := range dp {
for _, edge := range adj[state.u] {
v := edge.to
W := edge.W
new_lenW := state.lenW + int8(len(W))
if new_lenW > int8(2*n) {
continue
}
is_P := state.is_P_longer
excess := state.excess
valid := true
new_is_P := false
new_excess := ""
if !is_P {
if len(excess) > 0 {
if excess[0] != byte(v) {
valid = false
} else {
new_excess = excess[1:] + W
if len(new_excess) > 0 {
new_is_P = false
} else {
new_is_P = true
}
}
}
} else {
SP := excess + string([]byte{byte(v)})
L := len(SP)
if len(W) < L {
L = len(W)
}
if SP[:L] != W[:L] {
valid = false
} else {
if len(SP) > len(W) {
new_is_P = true
new_excess = SP[L:]
} else if len(SP) < len(W) {
new_is_P = false
new_excess = W[L:]
} else {
new_is_P = true
new_excess = ""
}
}
}
if valid {
ns := State{
u: v,
lenW: new_lenW,
is_P_longer: new_is_P,
excess: new_excess,
}
next_dp[ns] = (next_dp[ns] + count) % MOD
}
}
}
dp = next_dp
}
for i := 1; i <= 2*n; i++ {
fmt.Println(ans[i])
}
}
```