#include <bits/stdc++.h>   using namespace std;   const int max_n = 1500555, inf = 1000111222;   struct tree {     long long a[4 * max_n], f[4 * max_n];     void clr() {       memset(a, 0, sizeof(a));       memset(f, 0, sizeof(f));     }     void push(int v, int l, int r) {       if (f[v] != 0) {         f[2 * v] += f[v];         f[2 * v + 1] += f[v];         int mid = (l + r) / 2;         a[2 * v] += (mid - l + 1) * f[v];         a[2 * v + 1] += (r - mid) * f[v];         f[v] = 0;       }     }     void update(int v, int tl, int tr, int l, int r, long long value) {       if (tl == l && tr == r) {         a[v] += (r - l + 1) * value;         f[v] += value;         return;       }       push(v, tl, tr);       int mid = (tl + tr) / 2;       if (r <= mid) {         update(2 * v, tl, mid, l, r, value);       } else if (l > mid) {         update(2 * v + 1, mid + 1, tr, l, r, value);       } else {         update(2 * v, tl, mid, l, mid, value);         update(2 * v + 1, mid + 1, tr, mid + 1, r, value);       }       a[v] = (a[2 * v] + a[2 * v + 1]);     }     long long get_sum(int v, int tl, int tr, int l, int r) {       if (l > r) {         return 0;       }       if (tl == l && tr == r) {         return a[v];       }       push(v, tl, tr);       int mid = (tl + tr) / 2;       if (r <= mid) {         return get_sum(2 * v, tl, mid, l, r);       }       if (l > mid) {         return get_sum(2 * v + 1, mid + 1, tr, l, r);       }       return get_sum(2 * v, tl, mid, l, mid) +              get_sum(2 * v + 1, mid + 1, tr, mid + 1, r);     }   };   char buf[max_n];   string read() {     scanf( %s , buf);     return buf;   }   void get_z_function(const string &s, int z[]) {     z[0] = 0;     int l = 0, r = 0;     for (int i = 1; i < s.length(); ++i) {       z[i] = 0;       if (i <= r) {         z[i] = min(z[i - l], r - i + 1);       }       while (i + z[i] < s.length() && s[i + z[i]] == s[z[i]]) {         ++z[i];       }       if (i + z[i] - 1 > r) {         r = i + z[i] - 1;         l = i;       }     }   }   int n, m, z[2][max_n], mx[2][max_n], cnt[2][max_n];   string a[2], s, rs;   long long ans;   tree t;   vector<int> v[max_n];   void proc1() {     t.clr();     for (int i = 0; i < max_n; ++i) {       v[i].clear();     }     for (int i = 0; i < n; ++i) {       if (mx[0][i]) {         v[i + m - 1].push_back(max(1, m - mx[0][i]));       }     }     for (int i = 0; i < n; ++i) {       t.update(1, 0, m, 0, mx[1][i], 1);     }     for (int i = 0; i < n; ++i) {       for (int l : v[i]) {         ans -= t.get_sum(1, 0, m, l, m - 1);       }       t.update(1, 0, m, 0, mx[1][i], -1);     }   }   void proc2() {     t.clr();     for (int i = 0; i < max_n; ++i) {       v[i].clear();     }     for (int i = 0; i < n; ++i) {       if (mx[1][i]) {         v[i + 1].push_back(max(1, m - mx[1][i]));       }     }     for (int i = 0; i < n; ++i) {       t.update(1, 0, m, 0, mx[0][i], 1);     }     for (int i = 0; i < n; ++i) {       for (int l : v[i]) {         ans -= t.get_sum(1, 0, m, l, m - 1);       }       t.update(1, 0, m, 0, mx[0][i], -1);     }   }   int get_sum(int tp, int l, int r) {     if (!l) {       return cnt[tp][r];     }     return cnt[tp][r] - cnt[tp][l - 1];   }   int main() {     scanf( %d%d , &n, &m);     a[0] = read();     a[1] = read();     s = read();     rs = s;     reverse(rs.begin(), rs.end());     get_z_function(s +  #  + a[0], z[0]);     string ra1 = a[1];     reverse(ra1.begin(), ra1.end());     get_z_function(rs +  #  + ra1, z[1]);     for (int i = s.length() + 1; i <= s.length() + n; ++i) {       mx[0][i - (s.length() + 1)] = z[0][i];       mx[1][n - 1 - (i - (s.length() + 1))] = z[1][i];     }     proc1();     proc2();     for (int i = 0; i < 2; ++i) {       for (int j = 0; j < n; ++j) {         ++cnt[i][mx[i][j]];       }       for (int j = 1; j <= m; ++j) {         cnt[i][j] += cnt[i][j - 1];       }     }     for (int i = 1; i < m; ++i) {       const int s0 = get_sum(0, i, m);       const int s1 = get_sum(1, m - i, m);       ans += 1LL * s0 * s1;     }     printf( %I64d n , ans);     return 0;   }