Problem:
Problem H: Oh, My Goat!
太郎君は、次郎君に古文のノートを借りた。
明日の古文の宿題を写させてもらうためだ。
太郎君は、用心深い性格をしているため、万が一のことを考えて、近所のコンビニで次郎君のノートのコピーを取って自宅へ帰った。
太郎君は、自宅で宿題を始めようとしたときに、慌てた。
次郎君から借りたノートが鞄に入っていなかったからだ。
どうやら、コンビニに忘れてきてしまったようだ。
太郎君は、急いでコンビニに引き返した。
コピー機とその周辺を懸命に捜索したが、ノートを見つけることはできなかった。
困り果てた太郎君は、コンビニの店長に助けを求めた。
余談だが、店長は地球環境に優しい人で、白ヤギさんを飼っている。
店長は、地球環境に気を配る心遣いを持っているため、常日頃から、ペットの白ヤギさんに、餌としてコピー機周辺の客の忘れものを与えている。
店長によると、ノートは、今晩の白ヤギさんの晩御飯であり、白ヤギさんは現在食事中だそうである。
太郎君は白ヤギさんに頼みこみ、食べかけのノートを取り返すことはできたが、ノートはビリビリに破れぼろぼろである。
太郎君は、急いで自宅に引き返した。
自室の机とその周辺を懸命に捜索したが、ノートのコピーを見つけることはできなかった。
困り果てた太郎君は、お母さんに助けを求めた。
余談だが、太郎君のお母さんは地球環境に優しい人で、黒ヤギさんを飼っている。
太郎君のお母さんは、地球環境に気を配る心遣いを持っているため、常日頃から、ペットの黒ヤギさんに、餌として太郎君の宿題を与えている。
お母さんによると、ノートのコピーは、今晩の黒ヤギさんの晩御飯であり、黒ヤギさんは現在食事中だそうである。
太郎君は黒ヤギさんに頼みこみ、食べかけのノートを取り返すことはできたが、ノートのコピーはビリビリに破れぼろぼろである。
次郎君のノートとそのコピーをビリビリのぼろぼろにされてしまった太郎君は、ノートを可能な限り復元しようと考えた。
そこで、繋がりそうなノートの切れ端同士を繋ぎ合わせて、「繋ぎ合せたノート」を作成した。
同様に、繋がりそうなノートのコピーの切れ端同士を繋き合わせて、「繋ぎ合せたノートのコピー」を作成した。
太郎君は、あらゆる可能性を考えるために、繋がりそうな切れ端同士をつなぎ合わせた。
このため、1つの切れ目に2つ以上の切れ端が繋がれてしまった箇所もあった。
繋ぎ合わせ方の例を図1に示す。
図1は、7つの切れ端と6つの切れ目からなる。
図1
切れ端"haru"と"natsu"に続く切れ目には、切れ端"wa"が繋がり、文章が合流している。
切れ端"wa"に続く切れ目には、切れ端"ake"と"saron"が繋がり、文章が分岐している。
このような合流や切れ端があるため、図1は次のような4つの文章を表す。
haruwaakebono
haruwasaronpusu
natsuwaakebono
natsuwasaronpusu
ノートやノートのコピーは、白ヤギさんや黒ヤギさんが、食べてしまったため、復元できない部分があったり、彼らのご飯に混ざっていた関係のない書類の切れ端が混在していることもある。
太郎君の代わりに、「繋ぎ合わせたノート」と「繋ぎ合わせたノートのコピー」の2つを入力として受け取って、両方に共通して現れる文章の数を求めるプログラムを作成せよ。
Input
入力の1行目では、データセットの数
T
(
1 ≤ T ≤ 100
)が与えられる。
データセットは、「繋ぎ合せたノート」の情報と、「繋ぎ合せたノートのコピー」の情報から成る。
「繋ぎ合せたノート」の情報として、
1行目に
n
(
2 ≤ n ≤ 500
)と
m
(
1 ≤ m ≤ 600
)が与えられる。
n
は、切れ端と切れ端を繋ぎ合せる切れ目の数である。
続く
m
行で繋ぎ合せ方が与えられる。
各行は、切れ端の上端に繋がる切れ目の番号
a
、切れ端の下端につながる切れ目の番号
b
、切れ端を表す文字列
s
からなる。
ただし、
0 ≤ a < b < n
が満たされる。
s
は長さが1以上5以下の文字列で、アルファベットの小文字のみから成る。
「繋ぎ合せたノートのコピー」も「繋ぎ合せたノート」と同じ形式で与えられる。
なお、0番目の切れ目から繋ぎ合せ情報を辿り、
n-1
番目の切れ目に到達する過程で得られる文字列を連結したもののみを文章と呼ぶものとする。
また、それぞれの繋ぎ合せの中で同じ文章が2つ以上出現することはない。
Output
それぞれのデータセット毎に、答えの整数を1,000,000,007で割った余りを1行で出力せよ。
Sample Input
4
2 1
0 1 a
2 2
0 1 a
0 1 b
5 5
0 1 a
0 2 b
1 3 a
2 3 c
3 4 e
3 3
0 1 aa
0 2 bce
1 2 a
2 4
0 1 abc
0 1 def
0 1 ghi
0 1 jkl
2 4
0 1 ghi
0 1 jkl
0 1 mno
0 1 pqr
6 7
0 1 haru
0 1 natsu
1 2 wa
2 3 ake
2 4 saron
3 5 bono
4 5 pusu
5 4
0 1 haruw
1 2 aakeb
2 3 o
3 4 no
Output for Sample Input
1
1
2
1

Submitted solutions:

code_snippet: // AOJ #2288 Oh, My Goat!
// 2025.3.31

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MOD = 1000000007;

typedef vector<vector<pair<char,int>>> Automaton;

pair<Automaton, int> buildAutomaton(int n, int m, vector<tuple<int,int,string>> &edges) {
    int stateCount = n;
    Automaton aut;
    aut.resize(n + m*5);

    for(auto &edge : edges) {
        int u, v;
        string s;
        tie(u, v, s) = edge;
        int cur = u;
        for (int i = 0; i < (int)s.size(); i++) {
            char c = s[i];
            if(i == (int)s.size()-1) aut[cur].push_back({c, v});
            else {
                aut[cur].push_back({c, stateCount});
                cur = stateCount;
                stateCount++;
            }
        }
    }
    aut.resize(stateCount);
    return {aut, n-1};
}

ll dfs(int p, int q, const Automaton &aut1, const Automaton &aut2, int F1, int F2, int tot2, vector<ll> &dp) {
    int idx = p * tot2 + q;
    if(dp[idx] != -1) return dp[idx];
    ll ways = 0;
    if(p == F1 && q == F2) ways = 1;
    for(auto &edge1 : aut1[p]){
        char c = edge1.first;
        int np = edge1.second;
        for(auto &edge2 : aut2[q]){
            if(edge2.first == c){
                int nq = edge2.second;
                ways = (ways + dfs(np, nq, aut1, aut2, F1, F2, tot2, dp)) % MOD;
            }
        }
    }
    dp[idx] = ways;
    return ways;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int T;
    cin >> T;
    while(T--){
        int n1, m1;
        cin >> n1 >> m1;
        vector<tuple<int,int,string>> edges1;
        for (int i = 0; i < m1; i++){
            int a, b;
            string s;
            cin >> a >> b >> s;
            edges1.push_back({a, b, s});
        }
        auto res1 = buildAutomaton(n1, m1, edges1);
        Automaton aut1 = res1.first;
        int F1 = res1.second;

        int n2, m2;
        cin >> n2 >> m2;
        vector<tuple<int,int,string>> edges2;
        for (int i = 0; i < m2; i++){
            int a, b;
            string s;
            cin >> a >> b >> s;
            edges2.push_back({a, b, s});
        }
        auto res2 = buildAutomaton(n2, m2, edges2);
        Automaton aut2 = res2.first;
        int F2 = res2.second;

        int tot1 = aut1.size();
        int tot2 = aut2.size();

        vector<ll> dp(tot1 * tot2, -1);

        ll ans = dfs(0, 0, aut1, aut2, F1, F2, tot2, dp);
        cout << ans<< endl;
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 56788
final_rank: 11

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 605
struct Edge{

	int from,to;
	char buf[6];
	int len;
};

int N1,N2,M1,M2;
ll dp[SIZE][SIZE][6][6];
Edge edge1[SIZE],edge2[SIZE];
vector<int> G1[SIZE],G2[SIZE];

ll recursive(int e1,int loc1,int e2,int loc2){

	if(dp[e1][e2][loc1][loc2] != -1){

		return dp[e1][e2][loc1][loc2];
	}

	if(edge1[e1].buf[loc1] != edge2[e2].buf[loc2]){

		return dp[e1][e2][loc1][loc2] = 0;
	}

	ll ret = 0;

	if(loc1+1 < edge1[e1].len && loc2+1 < edge2[e2].len){ //両方非終端

		ret = recursive(e1,loc1+1,e2,loc2+1);

	}else if(loc1+1 == edge1[e1].len && loc2+1 < edge2[e2].len){ //DAG1が終端

		if(edge1[e1].to == N1-1){

			ret = 0;

		}else{ //DAG1が新しいノードへ

			for(int i = 0; i < G1[edge1[e1].to].size(); i++){

				ret += recursive(G1[edge1[e1].to][i],0,e2,loc2+1);
				ret %= MOD;
			}
		}

	}else if(loc1+1 < edge1[e1].len && loc2+1 == edge2[e2].len){ //DAG2が終端

		if(edge2[e2].to == N2-1){

			ret = 0;

		}else{ //DAG2が新しいノードへ

			for(int i = 0; i < G2[edge2[e2].to].size(); i++){

				ret += recursive(e1,loc1+1,G2[edge2[e2].to][i],0);
				ret %= MOD;
			}
		}

	}else{ //両方終端

		if((edge1[e1].to == N1-1 && edge2[e2].to != N2-1) ||
				(edge1[e1].to != N1-1 && edge2[e2].to == N2-1)){ //片方だけ文章完成

			ret = 0;

		}else if(edge1[e1].to == N1-1 && edge2[e2].to == N2-1){ //両方文章完成

			ret = 1;

		}else{ //両方新しいノードへ

			for(int i = 0; i < G1[edge1[e1].to].size(); i++){
				for(int k = 0; k < G2[edge2[e2].to].size(); k++){

					ret += recursive(G1[edge1[e1].to][i],0,G2[edge2[e2].to][k],0);
					ret %= MOD;
				}
			}
		}
	}

	return dp[e1][e2][loc1][loc2] = ret;
}


void func(){

	for(int i = 0; i < SIZE; i++){
		G1[i].clear();
		G2[i].clear();
	}

	scanf("%d %d",&N1,&M1);

	for(int i = 0; i < M1; i++){

		scanf("%d %d %s",&edge1[i].from,&edge1[i].to,edge1[i].buf);
		for(edge1[i].len = 0; edge1[i].buf[edge1[i].len] != '\0'; edge1[i].len++);

		G1[edge1[i].from].push_back(i);
	}

	scanf("%d %d",&N2,&M2);

	for(int i = 0; i < M2; i++){

		scanf("%d %d %s",&edge2[i].from,&edge2[i].to,edge2[i].buf);
		for(edge2[i].len = 0; edge2[i].buf[edge2[i].len] != '\0'; edge2[i].len++);

		G2[edge2[i].from].push_back(i);
	}

	for(int i = 0; i < M1; i++){
		for(int k = 0; k < M2; k++){
			for(int a = 0; a < 6; a++){
				for(int b = 0; b < 6; b++){
					dp[i][k][a][b] = -1;
				}
			}
		}
	}

	ll ans = 0;
	int root = 0;

	for(int i = 0; i < G1[root].size(); i++){
		for(int k = 0; k < G2[root].size(); k++){

			ans += recursive(G1[root][i],0,G2[root][k],0);
			ans %= MOD;
		}
	}

	printf("%lld\n",ans);
}

int main(){

	int num_case;
	scanf("%d",&num_case);

	for(int loop = 0; loop < num_case; loop++){

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 105420
final_rank: 14

code_snippet: #include <iostream> 
#include <sstream> 
#include <iomanip> 
#include <algorithm> 
#include <cmath> 
#include <string> 
#include <vector> 
#include <list> 
#include <queue> 
#include <stack> 
#include <set> 
#include <map> 
#include <bitset> 
#include <numeric> 
#include <climits> 
#include <cfloat> 
using namespace std;

const int MOD = 1000000007;

void input(int &n, int &m, vector<vector<int> >& to, vector<vector<string> >& str)
{
    cin >> n >> m;
    to.assign(n, vector<int>());
    str.assign(n, vector<string>());

    for(int i=0; i<m; ++i){
        int a, b;
        string s;
        cin >> a >> b >> s;
        to[a].push_back(b);
        str[a].push_back(s);
    }
}

bool compare(string& s, string& t)
{
    int n = min(s.size(), t.size());
    if(s.substr(0, n) != t.substr(0, n))
        return false;

    s = s.substr(n);
    t = t.substr(n);
    return true;
}

int main()
{
    int t;
    cin >> t;

    while(--t >= 0){
        int n1, m1, n2, m2;
        vector<vector<int> > to1, to2;
        vector<vector<string> > str1, str2;
        input(n1, m1, to1, str1);
        input(n2, m2, to2, str2);

        vector<vector<vector<map<string, int> > > > dp(n1, vector<vector<map<string, int> > >(n2, vector<map<string, int> >(2)));
        dp[0][0][0][""] = 1;

        for(int i=0; i<n1; ++i){
            for(int j=0; j<n2; ++j){
                if(i == n1-1 && j == n2-1)
                    break;

                while(!dp[i][j][0].empty()){
                    map<string, int>::iterator it = dp[i][j][0].begin();
                    string s0 = it->first;
                    int num = it->second;
                    dp[i][j][0].erase(it);

                    for(unsigned k=0; k<to1[i].size(); ++k){
                        int to = to1[i][k];
                        string s = s0;
                        string t = str1[i][k];
                        if(compare(s, t)){
                            if(t.size() == 0){
                                dp[to][j][0][s] += num;
                                dp[to][j][0][s] %= MOD;
                            }else{
                                dp[to][j][1][t] += num;
                                dp[to][j][1][t] %= MOD;
                            }
                        }
                    }
                }

                while(!dp[i][j][1].empty()){
                    map<string, int>::iterator it = dp[i][j][1].begin();
                    string s0 = it->first;
                    int num = it->second;
                    dp[i][j][1].erase(it);

                    for(unsigned k=0; k<to2[j].size(); ++k){
                        int to = to2[j][k];
                        string s = s0;
                        string t = str2[j][k];
                        if(compare(s, t)){
                            if(s.size() == 0){
                                dp[i][to][0][t] += num;
                                dp[i][to][0][t] %= MOD;
                            }else{
                                dp[i][to][1][s] += num;
                                dp[i][to][1][s] %= MOD;
                            }
                        }
                    }
                }
            }
        }

        cout << dp[n1-1][n2-1][0][""] << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 17000
final_rank: 10

code_snippet: #include <iostream>
#include <iomanip>
#include <sstream>
#include <cstdio>
#include <string>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cassert>
#include <climits>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
typedef long long ll;
typedef pair<int,int> pii;
const int INF = 1<<29;
const double PI = acos(-1);
const double EPS = 1e-8;

const int MOD = 1e9+7;

string str1[600];
string str2[600];
vector<int> g1[600], g2[600];
bool goal1[600], goal2[600];
int A[600], B[600];
int n1, m1;
int n2, m2;

int memo[600][6][600];

int solve(int p1, int q1, int p2, int q2) {
  //cout << p1 << " " << q1 << " " << p2 << " " <<  q2 << endl;
  if (q2 == 0 && memo[p1][q1][p2] >= 0) return memo[p1][q1][p2];
  if (!goal1[p1] && q1 == str1[p1].size()) {
    ll res = 0;
    FOR(it, g1[p1])
      res = (res + solve(*it, 0, p2, q2)) % MOD;
    if (q2 == 0) memo[p1][q1][p2] = res;
    return res;
  }
  if (!goal2[p2] && q2 == str2[p2].size()) {
    ll res = 0;
    FOR(it, g2[p2])
      res = (res + solve(p1, q1, *it, 0)) % MOD;
    return res;
  }
  bool f1 = (goal1[p1] && q1 == str1[p1].size());
  bool f2 = (goal2[p2] && q2 == str2[p2].size());
  int res;
  if (f1 || f2) {
    res = f1 && f2;
  } else {
    if (str1[p1][q1] == str2[p2][q2]) {
      res = solve(p1, q1+1, p2, q2+1);
    } else {
      res = 0;
    }
  }
  if (q2 == 0) memo[p1][q1][p2] = res;
  return res;
}

int main() {
  int T;
  cin >> T;
  while(T--) {
    cin >> n1 >> m1;
    REP(i, m1) g1[i].clear();
    memset(goal1, 0, sizeof(goal1));
    vector<int> start1;
    REP(i, m1) {
      cin >> A[i] >> B[i] >> str1[i];
      if (A[i] == 0) start1.push_back(i);
      if (B[i] == n1-1) goal1[i] = 1;
      REP(j, i) {
        if (B[j] == A[i]) {
          g1[j].push_back(i);
        }
      }
    }
    cin >> n2 >> m2;
    REP(i, m2) g2[i].clear();
    memset(goal2, 0, sizeof(goal2));
    vector<int> start2;
    REP(i, m2) {
      cin >> A[i] >> B[i] >> str2[i];
      if (A[i] == 0) start2.push_back(i);
      if (B[i] == n2-1) goal2[i] = 1;
      REP(j, i) {
        if (B[j] == A[i]) {
          g2[j].push_back(i);
        }
      }
    }
    ll res = 0;
    memset(memo,-1,sizeof(memo));
    FOR(it, start1) {
      FOR(jt, start2) {
        res = (res + solve(*it,0,*jt,0)) % MOD;
      }
    }
    cout << res << endl;
  }
}
accuracy: 1
time_ms: 70
memory_kb: 9688
final_rank: 8

code_snippet: #include<string>
#include<vector>
#include<cstring>
#include<iostream>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

const int M=1000000007;

struct edge{
	int u,v,id;
	string s;
};

int n1,n2;
edge E1[600],E2[600];
vector<int> adj1[500],adj2[500];

int dp[600][600][6];
int dfs(int i1,int i2,int p1,int p2){
	int dummy,&res=(p1==0?dp[i1][i2][p2]:dummy);
	if(p1==0 && ~res) return res;

	// 2 ÂÌ|C^ª¯É DAG ÌI[É½
	if(p1==E1[i1].s.length() && p2==E2[i2].s.length()){
		int v1=E1[i1].v,v2=E2[i2].v;
		if(v1==n1-1 && v2==n2-1) return res=1;
	}

	// |C^ 1 ª¶ñI[É½
	if(p1==E1[i1].s.length()){
		int v=E1[i1].v,cnt=0;
		rep(k,adj1[v].size()) cnt=(cnt+dfs(adj1[v][k],i2,0,p2))%M;
		return res=cnt;
	}

	// |C^ 2 ª¶ñI[É½
	if(p2==E2[i2].s.length()){
		int v=E2[i2].v,cnt=0;
		rep(k,adj2[v].size()) cnt=(cnt+dfs(i1,adj2[v][k],p1,0))%M;
		return res=cnt;
	}

	// wµÄ¢é¶ªá¤ÈçTõÅ¿Øè
	if(E1[i1].s[p1]!=E2[i2].s[p2]) return res=0;

	return res=dfs(i1,i2,p1+1,p2+1);
}

int main(){
	int T; cin>>T;
	while(T--){
		memset(dp,-1,sizeof dp);
		int m1; cin>>n1>>m1;
		rep(u,n1) adj1[u].clear();
		rep(j,m1){
			int u,v;
			string s; cin>>u>>v>>s;
			adj1[u].push_back(j);
			E1[j]=(edge){u,v,j,s};
		}
		int m2; cin>>n2>>m2;
		rep(u,n2) adj2[u].clear();
		rep(j,m2){
			int u,v;
			string s; cin>>u>>v>>s;
			adj2[u].push_back(j);
			E2[j]=(edge){u,v,j,s};
		}

		int ans=0;
		rep(i,adj1[0].size()) rep(j,adj2[0].size()) {
			ans=(ans+dfs(adj1[0][i],adj2[0][j],0,0))%M;
		}
		printf("%d\n",ans);
	}

	return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 9584
final_rank: 5

code_snippet: #include <iostream>
#include <fstream>
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <iomanip>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <sstream>
#include <string>
#include <vector>
using namespace std;

#define EPS 1e-9
#define INF MOD
#define MOD 1000000007LL
#define fir first
#define iss istringstream
#define sst stringstream
#define ite iterator
#define ll long long
#define mp make_pair
#define rep(i,n) rep2(i,0,n)
#define rep2(i,m,n) for(int i=m;i<n;i++)
#define pi pair<int,int>
#define pb push_back
#define sec second
#define sh(i) (1LL<<i)
#define sz size()
#define vi vector<int>
#define vc vector
#define vl vector<ll>
#define vs vector<string>

int T,n,m,N,M,a,b;
map<pi,int> dp;
string s;
struct E{int from;char c;E(int a,char b):from(a),c(b){}};
vc<E> e[3010],f[3010];

int F(int a,int b){
	if(dp.find(pi(a,b))!=dp.end())return dp[pi(a,b)];
	int& res=dp[pi(a,b)];
	if(!a&&!b)return res=1;
	rep(i,e[a].sz)rep(j,f[b].sz)if(e[a][i].c==f[b][j].c){
		res=(res+F(e[a][i].from,f[b][j].from))%MOD;
	}
	return res;
}

int main(){
	cin>>T;
	rep(tc,T){
		rep(i,3010)e[i].clear(),f[i].clear();
		cin>>n>>m;
		int cur=n;
		rep(i,m){
			cin>>a>>b>>s;
			if(s.sz==1)e[b].pb(E(a,s[0]));
			else rep(j,s.sz){
				if(j==0)e[cur].pb(E(a,s[j])),cur++;
				else if(j==s.sz-1)e[b].pb(E(cur-1,s[j]));
				else e[cur].pb(E(cur-1,s[j])),cur++;
			}
		}
		cin>>N>>M;
		cur=N;
		rep(i,M){
			cin>>a>>b>>s;
			if(s.sz==1)f[b].pb(E(a,s[0]));
			else rep(j,s.sz){
				if(j==0)f[cur].pb(E(a,s[j])),cur++;
				else if(j==s.sz-1)f[b].pb(E(cur-1,s[j]));
				else f[cur].pb(E(cur-1,s[j])),cur++;
			}
		}
		dp.clear();
		cout<<F(n-1,N-1)<<endl;
	}
}
accuracy: 1
time_ms: 20
memory_kb: 0
final_rank: 2

code_snippet: #include <cstring>
#include <iostream>
#include <cstdio>
#include <queue>
#define REP(i,n) for(int i=0; i<(int)(n); i++)

#define f first
#define s second
#define mp make_pair

using namespace std;

int n[2], m[2];

struct edge{
  int src;
  int dst;
  string label;

  edge(int s = 0, int d = 0, string l = "") :
    src(s), dst(d), label(l) {}
};

vector<edge> e[2];
vector<vector<int> > re[2];

int memo[600][600];
const int mod = 1000000007;

int solve(int id1, int id2, int l1, int l2){
  if(e[0][id1].dst == n[0] - 1    &&
     e[1][id2].dst == n[1] - 1    &&
     l1 == e[0][id1].label.size() &&
     l2 == e[1][id2].label.size())
    return 1;

  if(l1 == e[0][id1].label.size() &&
     l2 == e[1][id2].label.size() &&
     memo[id1][id2] != -1)
    return memo[id1][id2];
  
  int ret = 0;

  if(l1 == e[0][id1].label.size()){
    int src = e[0][id1].dst;

    REP(i, re[0][src].size()){
      int i1 = re[0][src][i];
      int i2 = id2;
      int ln1 = 0;
      int ln2 = l2;
      const string &s1 = e[0][i1].label;
      const string &s2 = e[1][i2].label;

      while(ln1 < s1.size() && ln2 < s2.size() && s1[ln1] == s2[ln2]){
	ln1++; ln2++;
      }

      if(ln1 == s1.size() || ln2 == s2.size()){
	ret = ((long long)ret + solve(i1, i2, ln1, ln2)) % mod;
      }
    }
  }else if(l2 == e[1][id2].label.size()){
    int src = e[1][id2].dst;

    REP(i, re[1][src].size()){
      int i1 = id1;
      int i2 = re[1][src][i];
      int ln1 = l1;
      int ln2 = 0;
      const string &s1 = e[0][i1].label;
      const string &s2 = e[1][i2].label;

      while(ln1 < s1.size() && ln2 < s2.size() && s1[ln1] == s2[ln2]){
	ln1++; ln2++;
      }

      if(ln1 == s1.size() || ln2 == s2.size()){
	ret = ((long long)ret + solve(i1, i2, ln1, ln2)) % mod;
      }
    }
  }else{
    printf("solve(%d, %d, %d, %d)\n", id1, id2, l1, l2);

    printf("e[0][%d].label: %s\n", id1, e[0][id1].label.c_str());
    printf("e[1][%d].label: %s\n", id2, e[1][id2].label.c_str());

    throw "error";
  }

  if(l1 == e[0][id1].label.size() &&
     l2 == e[1][id2].label.size())
    memo[id1][id2] = ret;

  return ret;
}

int main(){
  int t; cin >> t;
  while(t --> 0){
    REP(i,2){
      cin >> n[i] >> m[i];

      e[i]  = vector<edge>(m[i]);
      re[i] = vector<vector<int> >(n[i]);

      REP(j,m[i]){
	int s, d;
	string l;
	cin >> s >> d >> l;
	e[i][j] = edge(s, d, l);
	re[i][s].push_back(j);
      }
    }

    memset(memo, -1, sizeof(memo));

    int ans = 0;
    REP(i, re[0][0].size()) REP(j, re[1][0].size()){
      int id1 = re[0][0][i];
      int id2 = re[1][0][j];
      int l1 = 0;
      int l2 = 0;
      const string &s1 = e[0][id1].label;
      const string &s2 = e[1][id2].label;

      while(l1 != s1.size() && l2 != s2.size() && s1[l1] == s2[l2]){
	l1++; l2++;
      }

      if(l1 == s1.size() || l2 == s2.size()){
	ans = ((long long)ans + solve(id1, id2, l1, l2)) % mod;
      }
    }

    printf("%d\n", ans);
  }

  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 0
final_rank: 1

code_snippet: #include <stdio.h>
#include <iostream>
#include <vector>
#include <list>
#include <cmath>
#include <fstream>
#include <algorithm>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <complex>
#include <iterator>
#include <cstdlib>
#include <cstring>
#include <sstream>

using namespace std;

#define EPS (1e-10)
#define EQ(a,b) (abs((a) - (b)) < EPS)
#define EQV(a,b) (EQ((a).real(),(b).real()) && EQ((a).imag(),(b).imag()))

typedef complex<double> P;
typedef long long ll;

struct edge{
    int to;
    char ch;
};

vector<edge> G[2][4000];
// dp[i][j]->m[gÌm[hði,m[gÌRs[Ìm[hðjÆµ½Æ«A»±ÜÅÉ¤ÊµÄ»êé¶ÍÌ
//int dp[3600][3600];
map<int,map<int,int> > dp;
int n[2],m[2];

const int INF=-1;
const int MOD=1000000007;

int dfs(int idx1,int idx2){
    //if(dp[idx1][idx2]!=-1)
    //    return dp[idx1][idx2];
    if(!(dp.find(idx1)==dp.end()||dp[idx1].find(idx2)==dp[idx1].end()))
        return dp[idx1][idx2];
    if(idx1==0&&idx2==0)
        return 1;
    else if(idx1==0||idx2==0)
        return 0;
    // »ÝÌn_É¢½é[gð·×Ä²×ã°é
    // ßèûÌgÝí¹ðXgAbvµA·×Ä²×é
    int res=0;
    for(int i = 0; i < G[0][idx1].size(); i++){
        edge back=G[0][idx1][i];
        for(int j = 0; j < G[1][idx2].size(); j++){
            edge back2=G[1][idx2][j];
            if(back.ch==back2.ch){
                res+=dfs(back.to,back2.to);
                res%=MOD;
            }
        }
    }
    return dp[idx1][idx2]=res%MOD;
}

int main(){

    int t;
    cin>>t;
    while(t--){
        dp.clear();
        //memset(dp,0,sizeof(dp));
        //for(int i = 0; i < 3600; i++)
        //    fill(dp[i],dp[i]+3600,INF);
        for(int j = 0; j < 2; j++)
            for(int i = 0; i < 4000; i++)
                G[j][i].clear();
        for(int j = 0; j < 2; j++){
            cin>>n[j]>>m[j];
            int idx=n[j];
            for(int i = 0; i < m[j]; i++){
                int from,to;
                string str;
                cin>>from>>to>>str;
                // ¶ñðª£µÄ»ê¼êÉidðÂ¯ÄGÉi[·é
                int prv=from;
                for(int k = 0; k < str.size(); k++){
                    edge e;
                    e.to=prv;
                    e.ch=str[k];
                    int tmp=idx;
                    if(k==str.size()-1){
                        tmp=to;
                    }
                    G[j][tmp].push_back(e);
                    prv=tmp;
                    if(k==str.size()-1)
                        break;
                    idx++;
                }
            }
        }
        // »ÄAÅ¦ã°
        int res=dfs(n[0]-1,n[1]-1);
        cout<<res%MOD<<endl;
    }

    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 0
final_rank: 2

code_snippet: #include <stdio.h>
#include <iostream>
#include <vector>
#include <list>
#include <cmath>
#include <fstream>
#include <algorithm>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <complex>
#include <iterator>
#include <cstdlib>
#include <cstring>
#include <sstream>

using namespace std;

#define EPS (1e-10)
#define EQ(a,b) (abs((a) - (b)) < EPS)
#define EQV(a,b) (EQ((a).real(),(b).real()) && EQ((a).imag(),(b).imag()))

typedef complex<double> P;
typedef long long ll;

struct edge{
    int to;
    char ch;
};

vector<edge> G[2][4000];
// dp[i][j]->m[gÌm[hði,m[gÌRs[Ìm[hðjÆµ½Æ«A»±ÜÅÉ¤ÊµÄ»êé¶ÍÌ
int dp[3600][3600];
int n[2],m[2];

const int INF=-1;
const int MOD=1000000007;

int dfs(int idx1,int idx2){
    if(dp[idx1][idx2]!=-1)
        return dp[idx1][idx2];
    if(idx1==0&&idx2==0)
        return 1;
    else if(idx1==0||idx2==0){
        return 0;
    }
    // »ÝÌn_É¢½é[gð·×Ä²×ã°é
    // ßèûÌgÝí¹ðXgAbvµA·×Ä²×é
    int res=0;
    for(int i = 0; i < G[0][idx1].size(); i++){
        edge back=G[0][idx1][i];
        for(int j = 0; j < G[1][idx2].size(); j++){
            edge back2=G[1][idx2][j];
            if(back.ch==back2.ch){
                res+=dfs(back.to,back2.to);
                res%=MOD;
            }
        }
    }
    return dp[idx1][idx2]=res%MOD;
}

int main(){

    int t;
    cin>>t;
    while(t--){
        //memset(dp,0,sizeof(dp));
        for(int i = 0; i < 3600; i++)
            fill(dp[i],dp[i]+3600,INF);
        for(int j = 0; j < 2; j++)
            for(int i = 0; i < 4000; i++)
                G[j][i].clear();
        for(int j = 0; j < 2; j++){
            cin>>n[j]>>m[j];
            int idx=n[j];
            for(int i = 0; i < m[j]; i++){
                int from,to;
                string str;
                cin>>from>>to>>str;
                // ¶ñðª£µÄ»ê¼êÉidðÂ¯ÄGÉi[·é
                int prv=from;
                for(int k = 0; k < str.size(); k++){
                    edge e;
                    e.to=prv;
                    e.ch=str[k];
                    int tmp=idx;
                    if(k==str.size()-1){
                        tmp=to;
                    }
                    G[j][tmp].push_back(e);
                    prv=tmp;
                    if(k==str.size()-1)
                        break;
                    idx++;
                }
            }
        }
        // »ÄAÅ¦ã°
        int res=dfs(n[0]-1,n[1]-1);
        cout<<res%MOD<<endl;
    }

    return 0;
}
accuracy: 1
time_ms: 580
memory_kb: 0
final_rank: 13

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>
#include <map>

using namespace std;
 
int n[2],m[2];
map< pair<string,string> , int > memo[501][501];
vector< vector<int> > a[2];
vector< vector<string> > b[2];
 
int dfs(int p1,int p2,string s1,string s2){
        if(p1 == n[0]-1 && p2 == n[1]-1) return (s1 == "" && s2 == "");
		if(memo[p1][p2].count(make_pair(s1,s2))) return memo[p1][p2][make_pair(s1,s2)];

        int ans = 0;
		if(p1 <= p2 || p2 == n[1]-1){
			for(int i = 0 ; i < a[0][p1].size() ; i++){
					string x = s1 + b[0][p1][i];
					string y = s2;
					int I = 0 , J = 0;
					for( ; I < x.size() && J < y.size() && x[I] == y[J] ; ) I++ , J++ ;
					if( I == x.size() || J == y.size() ){
							
							if( I == x.size() && I == y.size() ) x = "" , y = "";
							else if( I == x.size() ) x = "" , y = y.substr(J);
							else if( J == y.size() ) x = x.substr(I) , y = "";
							
							ans = ( ans + dfs(a[0][p1][i],p2,x,y) ) % 1000000007;
					}
			}
		}
        
		if(p1 > p2 || p1 == n[0]-1){
			for(int j = 0 ; j < a[1][p2].size() ; j++){
					string x = s1;
					string y = s2 + b[1][p2][j] ;
					int I = 0 , J = 0;
					for( ; I < x.size() && J < y.size() && x[I] == y[J] ; ) I++ , J++ ;
					if( I == x.size() || J == y.size() ){
							
							if( I == x.size() && I == y.size() ) x = "" , y = "";
							else if( I == x.size() ) x = "" , y = y.substr(J);
							else if( J == y.size() ) x = x.substr(I) , y = "";
							
							ans = ( ans + dfs(p1, a[1][p2][j],x,y) ) % 1000000007;
					}
			}
		}
        return memo[p1][p2][make_pair(s1,s2)] = ans;
}
 
int main(){
        int T;cin >> T;
        while(T--){
                for(int i = 0 ; i < 2 ; i++){
                        cin >> n[i] >> m[i];
                        //cout << n[i] << " " << m[i] << endl;
                        a[i].clear(); b[i].clear(); a[i].resize((unsigned)n[i]) , b[i].resize((unsigned)n[i]);
                        for(int j = 0 ; j < m[i] ; j++){
                                int A,B; string C;
                                cin >> A >> B >> C;
                                a[i][A].push_back(B);
                                b[i][A].push_back(C);
                        }
                }
				for(int i = 0 ; i < 501 ; i++)
					for(int j = 0 ; j < 501 ; j++)
						memo[i][j].clear();
                cout << dfs(0,0,"","") << endl;
        }
}
accuracy: 1
time_ms: 80
memory_kb: 7756
final_rank: 7

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>
#include <map>

using namespace std;
 
int n[2],m[2];
map< pair<string,string> , int > memo[501][501];
vector< vector<int> > a[2];
vector< vector<string> > b[2];
 
int dfs(int p1,int p2,string s1,string s2){
        //cout << p1 << " " << p2 << " [" << s1 << "] [" << s2 << "]" << "{" << n[0] << " " << n[1] << endl;
        if(p1 == n[0]-1 && p2 == n[1]-1) return (s1 == "" && s2 == "");
		if(memo[p1][p2].count(make_pair(s1,s2))) return memo[p1][p2][make_pair(s1,s2)];

        int ans = 0;
		if(p1 <= p2 || p2 == n[1]-1){
			for(int i = 0 ; i < a[0][p1].size() ; i++){
					string x = s1 + b[0][p1][i];
					string y = s2;
					int I = 0 , J = 0;
					for( ; I < x.size() && J < y.size() && x[I] == y[J] ; ) I++ , J++ ;
					if( I == x.size() || J == y.size() ){
							
							if( I == x.size() && I == y.size() ) x = "" , y = "";
							else if( I == x.size() ) x = "" , y = y.substr(J);
							else if( J == y.size() ) x = x.substr(I) , y = "";
							
							ans = ( ans + dfs(a[0][p1][i],p2,x,y) ) % 1000000007;
					}
			}
		}
        
		if(p1 > p2 || p1 == n[0]-1){
			for(int j = 0 ; j < a[1][p2].size() ; j++){
					string x = s1;
					string y = s2 + b[1][p2][j] ;
					int I = 0 , J = 0;
					for( ; I < x.size() && J < y.size() && x[I] == y[J] ; ) I++ , J++ ;
					if( I == x.size() || J == y.size() ){
							
							if( I == x.size() && I == y.size() ) x = "" , y = "";
							else if( I == x.size() ) x = "" , y = y.substr(J);
							else if( J == y.size() ) x = x.substr(I) , y = "";
							
							ans = ( ans + dfs(p1, a[1][p2][j],x,y) ) % 1000000007;
					}
			}
		}
        return memo[p1][p2][make_pair(s1,s2)] = ans;
}
 
int main(){
        int T;cin >> T;
        while(T--){
                for(int i = 0 ; i < 2 ; i++){
                        cin >> n[i] >> m[i];
                        //cout << n[i] << " " << m[i] << endl;
                        a[i].clear(); b[i].clear(); a[i].resize((unsigned)n[i]) , b[i].resize((unsigned)n[i]);
                        for(int j = 0 ; j < m[i] ; j++){
                                int A,B; string C;
                                cin >> A >> B >> C;
                                a[i][A].push_back(B);
                                b[i][A].push_back(C);
                        }
                }
				for(int i = 0 ; i < 501 ; i++)
					for(int j = 0 ; j < 501 ; j++)
						memo[i][j].clear();
                cout << dfs(0,0,"","") << endl;
        }
}
accuracy: 1
time_ms: 80
memory_kb: 0
final_rank: 4

code_snippet: #include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
#define rep(i, n) for(int i=0; i<(int)(n); i++)
typedef long long Int;
#define MOD (1000000007)
inline void up(int &a, int b) { a = (a+b)%MOD; }

template<class W>
struct E {
    int u, v;
    W w;
    E() {}
    E(int u, int v, const W& w) : u(u), v(v), w(w) {}
};
template<class W>
bool less_u(const E<W>& l, const E<W>& r) {
    return l.u!=r.u ? l.u<r.u : l.v!=r.v ? l.v<r.v : l.w<r.w;
}

int N[2], M[2];
int of(int x, int y, int i, int j) {
    return (((x*600)+y)*16+i)*16+j;
}

int main() {
    int T;
    scanf("%d", &T);
    vector<E<string> > g[2];
    map<int, int> dp;
    while(T--) {
        vector<vector<int> > to[2];
        rep(k, 2) {
            scanf("%d%d", N+k, M+k);
            g[k].clear();
            rep(i, M[k]) {
                int a, b;
                char buf[8];
                scanf("%d%d%s", &a, &b, buf);
                g[k].push_back(E<string>(a, b, buf));
            }
            sort(g[k].begin(), g[k].end(), less_u<string>);
            to[k] = vector<vector<int> >(N[k]);
            rep(i, M[k]) {
                const int u = g[k][i].u;
                to[k][u].push_back(i);
            }
            to[k][N[k]-1].push_back(M[k]);
        }
        dp.clear();
        rep(i, to[0][0].size()) rep(j, to[1][0].size()) {
            const int ix = to[0][0][i], jx = to[1][0][j];
            dp[of(ix, jx, 0, 0)] = 1;
        }
        rep(x, M[0]) rep(y, M[1]) {
            const int v0 = g[0][x].v, v1 = g[1][y].v;
            const string &a = g[0][x].w, &b = g[1][y].w;
            rep(i, a.size()) rep(j, b.size()) if(a[i]==b[j]) {
                const int cur = of(x, y, i, j);
                if(dp.count(cur)==0) continue;
                const int val = dp[cur];
                if(i<(int)a.size()-1 && j<(int)b.size()-1) {
                    up(dp[of(x, y, i+1, j+1)], val);
                }
                else if(i<(int)a.size()-1) {
                    rep(p, to[1][v1].size()) {
                        const int ix = to[1][v1][p];
                        up(dp[of(x, ix, i+1, 0)], val);
                    }
                }
                else if(j<(int)b.size()-1) {
                    rep(p, to[0][v0].size()) {
                        const int ix = to[0][v0][p];
                        up(dp[of(ix, y, 0, j+1)], val);
                    }
                }
                else {
                    rep(p, to[0][v0].size()) rep(q, to[1][v1].size()) {
                        const int ix = to[0][v0][p];
                        const int jx = to[1][v1][q];
                        up(dp[of(ix, jx, 0, 0)], val);
                    }
                }
            }
        }
        printf("%d\n", dp[of(M[0], M[1], 0, 0)]);
    }
    return 0;
}
accuracy: 1
time_ms: 370
memory_kb: 2388
final_rank: 12

code_snippet: #include <iostream>
#include <cctype>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <cmath>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;

#define rep(i, n) for(int i = 0; i < n; i++)
typedef long long ll;
typedef pair<int, int> P;
typedef pair<int,P> PP;
const int INF = 1 << 29;
const int mod = 1000000007;

struct edge{
  int to;
  string s;
  edge(){}
  edge(int to, string s){
    this->to = to;
    this->s = s;
  }
};

bool ok(const string &s1, const string &s2){
  int n = s1.size();
  rep(i, n) if(s1[i] != s2[i]) return false;
  return true;
}


map<string, ll> dp[600][600][2];

vector<edge> G[2][600];


int main(){
  int T;
  cin >> T;
  int n1, m1, n2, m2;
  int a, b;
  string s, nxt;
  edge e;
  rep(t, T){
    cin >> n1 >> m1;
    rep(i, 600)rep(j, 2) G[j][i].clear();
    rep(i, 600)rep(j, 600)rep(k, 2) dp[i][j][k].clear(); 
    rep(i, m1){
      cin  >> a >> b >> s;
      G[0][a].push_back(edge(b, s));
    }
    cin >> n2 >> m2;
    rep(i, m2){
      cin >> a >> b >> s;
      G[1][a].push_back(edge(b, s));
    }
    dp[0][0][0][""] = 1;
    rep(i, n1)rep(j, n2){
      rep(k, 2){
	for(map<string, ll>::iterator iter = dp[i][j][k].begin(); 
	    iter != dp[i][j][k].end(); iter++){
	  string s = (*iter).first;
	  ll d = (*iter).second;
	  if(k == 1){
	    rep(v, (int)G[k][j].size()){
	      e = G[k][j][v];
	      if(e.s.size() < s.size() && ok(e.s, s)){
		nxt = string(s.begin() + e.s.size(), s.end());
		dp[i][e.to][1][nxt] = (dp[i][e.to][1][nxt] + d) % mod;
	      }
	      if(e.s.size() >= s.size() && ok(s, e.s)){
		nxt = string(e.s.begin() + s.size(), e.s.end());
		dp[i][e.to][0][nxt] = (dp[i][e.to][0][nxt] + d) % mod;
	      }
	    }
	  }else{
	    rep(v, (int)G[k][i].size()){ 
	      e = G[k][i][v];
	      if(e.s.size() <= s.size() && ok(e.s, s)){
		nxt = string(s.begin() + e.s.size(), s.end());
		dp[e.to][j][0][nxt] = (dp[e.to][j][0][nxt] + d) % mod;
	      }
	      if(e.s.size() > s.size() && ok(s, e.s)){
		nxt = string(e.s.begin() + s.size(), e.s.end());
		dp[e.to][j][1][nxt] = (dp[e.to][j][1][nxt] + d) % mod;
	      }
	    }
	  }
	}
      }
    }

    cout << dp[n1-1][n2-1][0][""] << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 0
final_rank: 9

code_snippet: #include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <assert.h>
#include <vector>
#include <string>
#include <map>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c) for (__typeof((c).begin())it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

struct State {
  int left;
  int right;
  int lr;
  int cnt;
  State() {;}
  State(int left, int right, int lr, int cnt) : left(left), right(right), lr(lr), cnt(cnt) {;}
  bool operator<(const State &rhs) const {
    if (left != rhs.left) { return left < rhs.left; }
    if (right != rhs.right) { return right < rhs.right; }
    if (lr != rhs.lr) { return lr < rhs.lr; }
    return cnt < rhs.cnt;
  }
};

const ll MOD = 1000000007;
int n[2];
int m[2];
vector<string> strs[2];
vector<vector<int> > from[2];
vector<int> to[2];
map<State, ll> memo;

ll calc(int left, int right, int lr, int cnt);
ll NextState(int left, int right, int lr, int cnt) {
  ll ret = 0;
  if (lr == 0) {
    FORIT(it, from[1][right]) {
      ret = (ret + calc(left, *it, lr, cnt)) % MOD;
    }
  } else {
    FORIT(it, from[0][left]) {
      ret = (ret + calc(*it, right, lr, cnt)) % MOD;
    }
  }
  return ret;
}

ll calc(int left, int right, int lr, int cnt) {
  if (left == m[0] && right == m[1]) { return 1; }
  State state(left, right, lr, cnt);
  if (memo.count(state)) { return memo[state]; }
  ll ret = 0;
  const string &lstr = strs[0][left];
  const string &rstr = strs[1][right];
  if (lr == 0 && (int)lstr.size() == cnt) {
    ret = NextState(to[0][left], right, 1, 0);
  } else if (lr == 1 && (int)rstr.size() == cnt) {
    ret = NextState(left, to[1][right], 0, 0);
  } else {
    int lindex = 0;
    int rindex = 0;
    if (lr == 0) { lindex = cnt; }
    else { rindex = cnt; }
    while (lindex < (int)lstr.size() && rindex < (int)rstr.size()) {
      if (lstr[lindex] != rstr[rindex]) { goto end; }
      lindex++;
      rindex++;
    }
    if (lindex == (int)lstr.size()) {
      ret = NextState(to[0][left], right, 1, rindex);
    } else {
      ret = NextState(left, to[1][right], 0, lindex);
    }
  }
end:
  return memo[state] = ret;
}

char str[100];
int main() {
  int test;
  scanf("%d", &test);
  while (test--) {
    memo.clear();
    REP(iter, 2) {
      scanf("%d %d", &n[iter], &m[iter]);
      from[iter].clear();
      strs[iter].resize(m[iter] + 1);
      from[iter].resize(n[iter]);
      to[iter].resize(m[iter]);
      REP(i, m[iter]) {
        int f, t;
        scanf("%d %d %s", &f, &t, str);
        from[iter][f].push_back(i);
        to[iter][i] = t;
        strs[iter][i] = str;
      }
      from[iter][n[iter] - 1].push_back(m[iter]);
      strs[iter][m[iter]] = "!";
    }
    ll ans = 0;
    FORIT(lit, from[0][0]) {
      ans = (ans + NextState(*lit, 0, 0, 0)) % MOD;
    }
    printf("%lld\n", ans);
  }
}
accuracy: 1
time_ms: 100
memory_kb: 2576
final_rank: 6