#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair <int,int> pii;
typedef pair <ll,ll> pll;

#define si(a)           scanf("%d",&a)
#define sii(a,b)        scanf("%d %d",&a,&b)
#define siii(a,b,c)     scanf("%d %d %d",&a,&b,&c)

#define sl(a)           scanf("%lld",&a)
#define sll(a,b)        scanf("%lld %lld",&a,&b)
#define slll(a,b,c)     scanf("%lld %lld %lld",&a,&b,&c)

#define un(x)           x.erase(unique(all(x)), x.end())
#define xx              first
#define yy              second
#define pb              push_back
#define mp              make_pair
#define all(v)          v.begin(),v.end()
#define D(x)            cerr << #x " = " << x << '\n'
#define DBG             cerr << "Hi!" << '\n'

#define CLR(a)          memset(a,0,sizeof(a))
#define SET(a)          memset(a,-1,sizeof(a))

#define PI              acos(-1.0)

//inline int setBit(int n,int pos) { return n = n | (1 << pos); }
//inline int resetBit(int n,int pos) { return n = n & ~(1 << pos); }
//inline bool checkBit(int n,int pos) { return (bool)(n & (1 << pos)); }
//inline int countBit(ll n) { return __builtin_popcountll(n); }

//int fx[] = {+0, +0, +1, -1, -1, +1, -1, +1};
//int fy[] = {-1, +1, +0, +0, +1, +1, -1, -1}; //Four & Eight Direction

/******************************************************************************************/

const int MAX = 30010;
//const int INF = 0x3f3f3f3f;
//const double inf = 1.0/0.0;
const int MOD = 1000000007;
//inline int add(int a,int b) { return (a + 0LL + b) % MOD; }
//inline int mul(int a,int b) { return (a * 1LL * b) % MOD; }

int bs;
int ara[MAX];
int ans[MAX];
int ways[105];

struct data {
    int l, r, id, x;
    inline data() {}
    inline data(int _l, int _r, int _x, int _id) {
        l = _l, r = _r, id = _id, x = _x;
    }
};

bool cmp(data a,data b) { return a.r < b.r; }

vector <data> Q[200];

inline void add(int p) {
    int x = ara[p];
    for(int i=100;i>=x;i--) ways[i] = (ways[i-x] + ways[i]) % MOD;
}

inline void addBlock(int id) {
    int L = bs*id, R = L + bs;
    for(int i=L;i<R;i++) add(i);
}

bitset <101> B;
vector <int> S;
int save[105];

inline void tempAdd(int p) {
    int x = ara[p];
    for(int i=100;i>=x;i--) {
        int a = ways[i];
        ways[i] = (ways[i-x] + ways[i]) % MOD;
        if(ways[i] != a and B[i] == 0) {
            B[i] = 1;
            save[i] = a;
            S.push_back(i);
        }
    }
}

void rollBack() {
    for(auto e : S) ways[e] = save[e];
    B = 0;
    S.clear();
}

void addRange(int L,int R) {
    for(int i=L;i<=R;i++) tempAdd(i);
}

void solve(int id) {
    CLR(ways);
    ways[0] = 1;
    int bnr;
    int nxt = id + 1;
    for(auto d : Q[id]) {
        bnr = d.r/bs;
        if(bnr == id) {
            addRange(d.l,d.r);
            ans[d.id] = ways[d.x];
            rollBack();
        }
        else {
            while(bnr > nxt) {
                addBlock(nxt);
                nxt++;
            }
            addRange(d.l,bs*(id+1)-1);
            addRange(bnr*bs,d.r);
            ans[d.id] = ways[d.x];
            rollBack();
        }
    }
}

int main() {
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);

    ios_base::sync_with_stdio(false);
    cin.tie(0);

    int T, n, q;
    cin >> T;
    for(int t=1;t<=T;t++) {

        CLR(ways);
        ways[0] = 1;

        int n, q, a, b, c;

        cin >> n >> q;
        bs = sqrt(n);

        for(int i=0;i<n;i++) cin >> ara[i];

        data d;

        for(int i=0;i<q;i++) {
            cin >> a >> b >> c;
            a--, b--;
            d = data(a,b,c,i);
            Q[a/bs].push_back(d);
        }
        for(int i=0;i<=((n-1)/bs);i++) sort(Q[i].begin(),Q[i].end(),cmp), solve(i), Q[i].clear();
        cout << "Case " << t << ":\n";
        for(int i=0;i<q;i++) cout << ans[i] << "\n";
    }
    return 0;
}


#include <bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
//using namespace __gnu_pbds;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair <int,int> pii;
typedef pair <ll,ll> pll;

#define si(a)           scanf("%d",&a)
#define sii(a,b)        scanf("%d %d",&a,&b)
#define siii(a,b,c)     scanf("%d %d %d",&a,&b,&c)

#define sl(a)           scanf("%lld",&a)
#define sll(a,b)        scanf("%lld %lld",&a,&b)
#define slll(a,b,c)     scanf("%lld %lld %lld",&a,&b,&c)

#define un(x)           x.erase(unique(all(x)), x.end())
#define xx              first
#define yy              second
#define pb              push_back
#define mp              make_pair
#define all(v)          v.begin(),v.end()
#define D(x)            cerr << #x " = " << x << '\n'
#define DBG             cerr << "Hi!" << '\n'

#define CLR(a)          memset(a,0,sizeof(a))
#define SET(a)          memset(a,-1,sizeof(a))

#define PI              acos(-1.0)

//inline int setBit(int n,int pos) { return n = n | (1 << pos); }
//inline int resetBit(int n,int pos) { return n = n & ~(1 << pos); }
//inline bool checkBit(int n,int pos) { return (bool)(n & (1 << pos)); }
//inline int countBit(ll n) { return __builtin_popcountll(n); }

//int fx[] = {+0, +0, +1, -1, -1, +1, -1, +1};
//int fy[] = {-1, +1, +0, +0, +1, +1, -1, -1}; //Four & Eight Direction

/******************************************************************************************/

const int MAX = 200010;
//const int INF = 0x3f3f3f3f;
//const double inf = 1.0/0.0;
//const int MOD = 1000000007;
//inline int add(int a,int b) { return (a + 0LL + b) % MOD; }
//inline int mul(int a,int b) { return (a * 1LL * b) % MOD; }

int dp[MAX];
int rp[MAX];

struct AC {
    int N, P;
    const int A = 26;
    vector < vector <int> > next;
    vector <int> link, out_link;
    vector < vector <int> > out;
    vector < int > cnt;
    vector < vector <int> > ed;

    AC(): N(0), P(0) { node(); }

    int node() {
        next.emplace_back(A, 0);
        link.emplace_back(0);
        out.emplace_back(0);
        out_link.emplace_back(0);
        cnt.emplace_back(0);
        ed.emplace_back(0);
        return N++;
    }

    void clear() {
        next.clear(), link.clear(), out.clear() , out_link.clear(), ed.clear();
        cnt.clear();
        N = P = 0;
        node();
    }

    inline int get(char c) { return c - 'a'; }

    void insert(const string &T) {
        int u = 0;
        for (char c : T) {
            if (!next[u][get(c)]) next[u][get(c)] = node();
            u = next[u][get(c)];
        }
        out[u].push_back(P);
        P++;
    }

    void build() {
        queue <int> q;
        for (q.push(0); !q.empty(); ) {
            int u = q.front();
            q.pop();
            for (int c = 0; c < A; ++c) {
                int v = next[u][c];
                if (!v) next[u][c] = next[link[u]][c];
                else {
                    link[v] = u ? next[link[u]][c] : 0;
                    out_link[v] = out[link[v]].empty() ? out_link[link[v]] : link[v];
                    ed[link[v]].push_back(v);
                    q.push(v);
                }
            }
        }
    }

    void dfs(int s,int sum) {
        cnt[s] = sum;
        for(int x : ed[s]) dfs(x,out[x].size() + sum);
    }

    void traverse(const string &S) {
        dfs(0,0);
        int u = 0;
        for(int i=0;i<S.size();i++) {
            u = next[u][get(S[i])];
            dp[i] = cnt[u];
        }
    }
};

string s, pat[200010];

int main() {
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);

    ios_base::sync_with_stdio(false);
    cin.tie(0);

    cin >> s;
    int n;
    cin >> n;
    for(int i=1;i<=n;i++) cin >> pat[i];

    AC aho;
    for(int i=1;i<=n;i++) aho.insert(pat[i]);
    aho.build();
    aho.traverse(s);

    for(int i=0;i<s.size();i++) rp[i] = dp[i];

    aho.clear();
    for(int i=1;i<=n;i++) {
        reverse(all(pat[i]));
        aho.insert(pat[i]);
    }
    aho.build();
    reverse(all(s));
    aho.traverse(s);

    ll ans = 0;

    for(int i=0;i<s.size();i++) {
        ans += (rp[i] * 1LL * dp[s.size()-i-1-1]);
    }
    cout << ans << endl;
    return 0;
}


#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int SIGMA_SIZE = 26;
const int MAXNODE = 500010;
struct AhoCorasickAutomata
{
    int ch[MAXNODE][SIGMA_SIZE];
    int f[MAXNODE];    // fail函数
    int val[MAXNODE];  // 每个字符串的结尾结点都有一个非0的val
    int last[MAXNODE]; // fail链上的下一个单词结尾结点
    int num[MAXNODE];
    int sz;
    int sum[MAXNODE];
    void init()
    {
        sz = 1;
        memset(ch[0], 0, sizeof(ch[0]));
    }
    int idx(char c){return c-'a';}
    // 插入字符串。v必须非0
    void insert(char *s, int v)
    {
        int u = 0, n = strlen(s);
        for(int i = 0; i < n; i++)
        {
            int c = idx(s[i]);
            if(!ch[u][c])
            {
                memset(ch[sz], 0, sizeof(ch[sz]));
                val[sz] = 0;
                ch[u][c] = sz++;
            }
            u = ch[u][c];
        }
        val[u] = v;
        sum[u]++;
    }
    // 递归打印以结点j结尾的所有字符串
    void print(int j,int i)
    {
        if(j)
        {
            //cnt[val[j]]++;
            //cout<<i<<" "<<j<<endl;
            num[i]+=sum[j];
            print(last[j],i);
        }
    }
    // 在T中找模板
    void find(char* T)
    {
        int n = strlen(T);
        int j = 0; // 当前结点编号，初始为根结点
        for(int i = 0; i < n; i++)
        {
            int c = idx(T[i]);
            j = ch[j][c];
            if(val[j]) print(j,i);
            else if(last[j]) print(last[j],i); // 找到了！
        }
    }
    // 计算fail函数
    void getFail()
    {
        queue<int> q;
        f[0] = 0;
        // 初始化队列
        for(int c = 0; c < SIGMA_SIZE; c++)
        {
            int u = ch[0][c];
            if(u) { f[u] = 0; q.push(u); last[u] = 0; }
        }
        // 按BFS顺序计算fail
        while(!q.empty())
        {
            int r = q.front(); q.pop();
            for(int c = 0; c < SIGMA_SIZE; c++)
            {
                int u = ch[r][c];
                if(!u) {ch[r][c] = ch[f[r]][c];continue;}
                q.push(u);
                int v = f[r];
                while(v && !ch[v][c]) v = f[v];
                f[u] = ch[v][c];
                last[u] = val[f[u]] ? f[u] : last[f[u]];
            }
        }
    }
}ac1,ac2;

int n;
char s[200010],t[200010];

int main()
{
    scanf("%s",t);
    ac1.init();ac2.init();
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%s",s);
        int len=strlen(s);
        ac1.insert(s,i);
        reverse(s,s+len);
        ac2.insert(s,i);
    }
    ac1.getFail();ac2.getFail();
    n=strlen(t);
    ac1.find(t);
    reverse(t,t+n);
    ac2.find(t);
    reverse(ac2.num,ac2.num+n);
    LL ans=0;
    for (int i=0;i<n-1;i++)
        ans+=ac1.num[i]*ac2.num[i+1];
    cout<<ans<<endl;
    return 0;
}


#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int SIGMA_SIZE = 26;
const int MAXNODE = 500010;
struct AhoCorasickAutomata
{
    int ch[MAXNODE][SIGMA_SIZE];
    int f[MAXNODE];    // fail函数
    int val[MAXNODE];  // 每个字符串的结尾结点都有一个非0的val
    int last[MAXNODE]; // fail链上的下一个单词结尾结点
    int num[MAXNODE];
    int sz;
    int sum[MAXNODE];
    void init()
    {
        sz = 1;
        memset(ch[0], 0, sizeof(ch[0]));
    }
    int idx(char c){return c-'a';}
    // 插入字符串。v必须非0
    void insert(char *s, int v)
    {
        int u = 0, n = strlen(s);
        for(int i = 0; i < n; i++)
        {
            int c = idx(s[i]);
            if(!ch[u][c])
            {
                memset(ch[sz], 0, sizeof(ch[sz]));
                val[sz] = 0;
                ch[u][c] = sz++;
            }
            u = ch[u][c];
        }
        val[u] = v;
        sum[u]++;
    }
    // 递归打印以结点j结尾的所有字符串
    void print(int j,int i)
    {
        if(j)
        {
            //cnt[val[j]]++;
            //cout<<i<<" "<<j<<endl;
            num[i]+=sum[j];
            print(last[j],i);
        }
    }
    // 在T中找模板
    void find(char* T)
    {
        int n = strlen(T);
        int j = 0; // 当前结点编号，初始为根结点
        for(int i = 0; i < n; i++)
        {
            int c = idx(T[i]);
            j = ch[j][c];
            if(val[j]) print(j,i);
            else if(last[j]) print(last[j],i); // 找到了！
        }
    }
    // 计算fail函数
    void getFail()
    {
        queue<int> q;
        f[0] = 0;
        // 初始化队列
        for(int c = 0; c < SIGMA_SIZE; c++)
        {
            int u = ch[0][c];
            if(u) { f[u] = 0; q.push(u); last[u] = 0; }
        }
        // 按BFS顺序计算fail
        while(!q.empty())
        {
            int r = q.front(); q.pop();
            for(int c = 0; c < SIGMA_SIZE; c++)
            {
                int u = ch[r][c];
                if(!u) {ch[r][c] = ch[f[r]][c];continue;}
                q.push(u);
                int v = f[r];
                while(v && !ch[v][c]) v = f[v];
                f[u] = ch[v][c];
                last[u] = val[f[u]] ? f[u] : last[f[u]];
            }
        }
    }
}ac1,ac2;

int n;
char s[200010],t[200010];

int main()
{
    scanf("%s",t);
    ac1.init();ac2.init();
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%s",s);
        int len=strlen(s);
        ac1.insert(s,i);
        reverse(s,s+len);
        ac2.insert(s,i);
    }
    ac1.getFail();ac2.getFail();
    n=strlen(t);
    ac1.find(t);
    reverse(t,t+n);
    ac2.find(t);
    reverse(ac2.num,ac2.num+n);
    LL ans=0;
    for (int i=0;i<n-1;i++)
        ans+=((LL)(ac1.num[i]))*((LL)ac2.num[i+1]);
    cout<<ans<<endl;
    return 0;
}


#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int SIGMA_SIZE = 26;
const int MAXNODE = 5000010;
const int MAXS = 200 + 10;
struct AhoCorasickAutomata
{
    int ch[MAXNODE][SIGMA_SIZE];
    int f[MAXNODE];    // fail函数
    int val[MAXNODE];  // 每个字符串的结尾结点都有一个非0的val
    int last[MAXNODE]; // fail链上的下一个单词结尾结点
    int num[MAXNODE];
    int sz;
    int sum[MAXNODE];
    void init()
    {
        sz = 1;
        memset(ch[0], 0, sizeof(ch[0]));
    }
    int idx(char c){return c-'a';}
    // 插入字符串。v必须非0
    void insert(char *s, int v)
    {
        int u = 0, n = strlen(s);
        for(int i = 0; i < n; i++)
        {
            int c = idx(s[i]);
            if(!ch[u][c])
            {
                memset(ch[sz], 0, sizeof(ch[sz]));
                val[sz] = 0;
                ch[u][c] = sz++;
            }
            u = ch[u][c];
        }
        val[u] = v;
        sum[u]++;
    }
    // 递归打印以结点j结尾的所有字符串
    void print(int j,int i)
    {
        if(j)
        {
            //cnt[val[j]]++;
            //cout<<i<<" "<<j<<endl;
            num[i]+=sum[j];
            print(last[j],i);
        }
    }
    // 在T中找模板
    void find(char* T)
    {
        int n = strlen(T);
        int j = 0; // 当前结点编号，初始为根结点
        for(int i = 0; i < n; i++)
        {
            int c = idx(T[i]);
            j = ch[j][c];
            if(val[j]) print(j,i);
            else if(last[j]) print(last[j],i); // 找到了！
        }
    }
    // 计算fail函数
    void getFail()
    {
        queue<int> q;
        f[0] = 0;
        // 初始化队列
        for(int c = 0; c < SIGMA_SIZE; c++)
        {
            int u = ch[0][c];
            if(u) { f[u] = 0; q.push(u); last[u] = 0; }
        }
        // 按BFS顺序计算fail
        while(!q.empty())
        {
            int r = q.front(); q.pop();
            for(int c = 0; c < SIGMA_SIZE; c++)
            {
                int u = ch[r][c];
                if(!u) {ch[r][c] = ch[f[r]][c];continue;}
                q.push(u);
                int v = f[r];
                while(v && !ch[v][c]) v = f[v];
                f[u] = ch[v][c];
                last[u] = val[f[u]] ? f[u] : last[f[u]];
            }
        }
    }
}ac1,ac2;

int n;
char s[200010],t[200010];

int main()
{
    scanf("%s",t);
    ac1.init();ac2.init();
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%s",s);
        int len=strlen(s);
        ac1.insert(s,i);
        reverse(s,s+len);
        ac2.insert(s,i);
    }
    ac1.getFail();ac2.getFail();
    n=strlen(t);
    ac1.find(t);
    reverse(t,t+n);
    ac2.find(t);
    reverse(ac2.num,ac2.num+n);
    LL ans=0;
    for (int i=0;i<n-1;i++)
        ans+=ac1.num[i]*ac2.num[i+1];
    cout<<ans<<endl;
    return 0;
}


#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int SIGMA_SIZE = 26;
const int MAXNODE = 5000010;
const int MAXS = 200 + 10;
struct AhoCorasickAutomata
{
    int ch[MAXNODE][SIGMA_SIZE];
    int f[MAXNODE];    // fail函数
    int val[MAXNODE];  // 每个字符串的结尾结点都有一个非0的val
    int last[MAXNODE]; // fail链上的下一个单词结尾结点
    int cnt[MAXS]; //用来统计模式串被找到了几次
    int num[MAXNODE];
    int sz;
    vector<int> S[MAXNODE];
    void init()
    {
        sz = 1;
        memset(ch[0], 0, sizeof(ch[0]));
        memset(cnt, 0, sizeof(cnt));
    }
    int idx(char c){return c-'a';}
    // 插入字符串。v必须非0
    void insert(char *s, int v)
    {
        int u = 0, n = strlen(s);
        for(int i = 0; i < n; i++)
        {
            int c = idx(s[i]);
            if(!ch[u][c])
            {
                memset(ch[sz], 0, sizeof(ch[sz]));
                val[sz] = 0;
                ch[u][c] = sz++;
            }
            u = ch[u][c];
        }
        val[u] = v;
        S[u].push_back(v);
    }
    // 递归打印以结点j结尾的所有字符串
    void print(int j,int i)
    {
        if(j)
        {
            cnt[val[j]]++;
            //cout<<i<<" "<<j<<endl;
            num[i]+=S[j].size();
            print(last[j],i);
        }
    }
    // 在T中找模板
    void find(char* T)
    {
        int n = strlen(T);
        int j = 0; // 当前结点编号，初始为根结点
        for(int i = 0; i < n; i++)
        {
            int c = idx(T[i]);
            j = ch[j][c];
            if(val[j]) print(j,i);
            else if(last[j]) print(last[j],i); // 找到了！
        }
    }
    // 计算fail函数
    void getFail()
    {
        queue<int> q;
        f[0] = 0;
        // 初始化队列
        for(int c = 0; c < SIGMA_SIZE; c++)
        {
            int u = ch[0][c];
            if(u) { f[u] = 0; q.push(u); last[u] = 0; }
        }
        // 按BFS顺序计算fail
        while(!q.empty())
        {
            int r = q.front(); q.pop();
            for(int c = 0; c < SIGMA_SIZE; c++)
            {
                int u = ch[r][c];
                if(!u) {ch[r][c] = ch[f[r]][c];continue;}
                q.push(u);
                int v = f[r];
                while(v && !ch[v][c]) v = f[v];
                f[u] = ch[v][c];
                last[u] = val[f[u]] ? f[u] : last[f[u]];
            }
        }
    }
}ac1,ac2;

int n;
char s[200010],t[200010];

int main()
{
    scanf("%s",t);
    ac1.init();ac2.init();
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%s",s);
        int len=strlen(s);
        ac1.insert(s,i);
        reverse(s,s+len);
        ac2.insert(s,i);
    }
    ac1.getFail();ac2.getFail();
    n=strlen(t);
    ac1.find(t);
    reverse(t,t+n);
    ac2.find(t);
    reverse(ac2.num,ac2.num+n);
    LL ans=0;
    for (int i=0;i<n-1;i++)
        ans+=ac1.num[i]*ac2.num[i+1];
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define fir first
#define sec second
#define mp(x, y) make_pair(x, y)
#define pb push_back
typedef long long ll;
typedef pair<int, int> PII;
const int N = 4e5 + 5;
const int Sig = 26;
const int inf = 0x3f3f3f3f;
int f[N], n;
ll ans;
queue<int> que;
char str[N], ss[N];
struct AC{
    int size[N], sum[N], fa[N], ch[N][Sig], len[N], sz;
    inline void ins(){
    	int l = strlen(ss + 1), now = 0;
    	for(int i = 1, cc; i <= l; ++i){
    		cc = ss[i] - 'a';
			if(!ch[now][cc]) ch[now][cc] = ++sz, len[sz] = i;
			now = ch[now][cc];
    	}
    	++size[now];
    }
    inline void build(){
        for(int i = 0; i < Sig; ++i)
            if(ch[0][i]) que.push(ch[0][i]), fa[ch[0][i]] = 0;
        while(!que.empty()){
        	int fro = que.front(); que.pop();
            sum[fro] = size[fro] + sum[fa[fro]];
        	for(int i = 0; i < Sig; ++i){
        		if(ch[fro][i]){
        		    fa[ch[fro][i]] = ch[fa[fro]][i];
					que.push(ch[fro][i]);
        		}
        		else ch[fro][i] = ch[fa[fro]][i];
        	}
        }
    }
    inline void solve(){
    	int l = strlen(str + 1), now = 0;
    	for(int i = 1, cc; i <= l; ++i){
    		cc = str[i] - 'a';
    		now = ch[now][cc], f[i] = now;
    		for(int j = now; j; j = fa[j]){
    			ans += 1ll * size[j] * sum[f[i - len[j]]];
    		}
    	//	printf("%d %lld\n", i, ans);
    	}
    }
}ac;

int main(){
	scanf("%s%d", str + 1, &n);
	for(int i = 1; i <= n; ++i){
		scanf("%s", ss + 1);
		ac.ins();
	}
	ac.build(), ac.solve();
	printf("%lld\n", ans);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define fir first
#define sec second
#define mp(x, y) make_pair(x, y)
#define pb push_back
typedef long long ll;
typedef pair<int, int> PII;
const int N = 4e5 + 5;
const int Sig = 26;
const int inf = 0x3f3f3f3f;
int f[N], n;
ll ans;
queue<int> que;
char str[N], ss[N];
struct AC{
    int size[N], sum[N], ff[N], fa[N], ch[N][Sig], len[N], sz;
    inline void ins(){
    	int l = strlen(ss + 1), now = 0;
    	for(int i = 1, cc; i <= l; ++i){
    		cc = ss[i] - 'a';
			if(!ch[now][cc]) ch[now][cc] = ++sz, len[sz] = i;
			now = ch[now][cc];
    	}
    	++size[now];
    }
    inline void build(){
        for(int i = 0; i < Sig; ++i)
            if(ch[0][i]) que.push(ch[0][i]), fa[ch[0][i]] = 0;
        while(!que.empty()){
        	int fro = que.front(); que.pop();
            sum[fro] = size[fro] + sum[fa[fro]];
            ff[fro] = size[fa[fro]] ? fa[fro] : ff[fa[fro]];
        	for(int i = 0; i < Sig; ++i){
        		if(ch[fro][i]){
        		    fa[ch[fro][i]] = ch[fa[fro]][i];
					que.push(ch[fro][i]);
        		}
        		else ch[fro][i] = ch[fa[fro]][i];
        	}
        }
    }
    inline void solve(){
    	int l = strlen(str + 1), now = 0;
    	for(int i = 1, cc; i <= l; ++i){
    		cc = str[i] - 'a';
    		now = ch[now][cc], f[i] = now;
    		for(int j = now; j; j = ff[j]){
    			ans += 1ll * size[j] * sum[f[i - len[j]]];
    		}
    	//	printf("%d %lld\n", i, ans);
    	}
    }
}ac;

int main(){
	scanf("%s%d", str + 1, &n);
	for(int i = 1; i <= n; ++i){
		scanf("%s", ss + 1);
		ac.ins();
	}
	ac.build(), ac.solve();
	printf("%lld\n", ans);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define fir first
#define sec second
#define mp(x, y) make_pair(x, y)
#define pb push_back
typedef long long ll;
typedef pair<int, int> PII;
const int N = 2e5 + 5;
const int Sig = 26;
const int inf = 0x3f3f3f3f;
int f[N], ans, n;
queue<int> que;
char str[N], ss[N];
struct AC{
    int size[N], sum[N], fa[N], ch[N][Sig], len[N], sz;
    inline void ins(){
    	int l = strlen(ss + 1), now = 0;
    	for(int i = 1, cc; i <= l; ++i){
    		cc = ss[i] - 'a';
			if(!ch[now][cc]) ch[now][cc] = ++sz, len[sz] = i;
			now = ch[now][cc];
    	}
    	++size[now];
    }
    inline void build(){
        for(int i = 0; i < Sig; ++i)
            if(ch[0][i]) que.push(ch[0][i]);
       // printf("*");
        while(!que.empty()){
        	int fro = que.front(); que.pop();
            sum[fro] = size[fro] + sum[fa[fro]];
        	for(int i = 0; i < Sig; ++i){
        		if(ch[fro][i]){
        		    fa[ch[fro][i]] = ch[fa[fro]][i];
					que.push(ch[fro][i]);
        		}
        		else ch[fro][i] = ch[fa[fro]][i];
        	}
        }
    }
    inline void solve(){
    	int l = strlen(str + 1), now = 0;
    	for(int i = 1, cc; i <= l; ++i){
    		cc = str[i] - 'a';
    		now = ch[now][cc], f[i] = now;
    		for(int j = now; j; j = fa[j]){
    			ans += size[j] * sum[f[i - len[j]]];
    		}
    	}
    }
}ac;

int main(){
	scanf("%s%d", str + 1, &n);
	for(int i = 1; i <= n; ++i){
		scanf("%s", ss + 1);
		ac.ins();
	}
	ac.build(), ac.solve();
	printf("%d\n", ans);
	return 0;
}


#include<bits/stdc++.h>
#define N 200010
#define INF 0x3f3f3f3f
#define eps 1e-6
#define pi acos(-1.0)
#define mod 998244353
#define P 1000000007
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define bug(x) cerr<<#x<<"      :   "<<x<<endl
#define mem(x) memset(x,0,sizeof x)
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
struct Trie{
    int t[N][26],fail[N],d[N],w[N];
    int tot;
    void init(){ tot=0;
        memset(fail,0,sizeof fail);
        memset(t,0,sizeof t);
        memset(d,0,sizeof d);
    }
    void ins(char* x){
        int i=0;
        for(int j=0;x[j];j++){
            int c=x[j]-'a';
            if(!t[i][c]) t[i][c]=++tot;
            i=t[i][c];
        }
        d[i]++;
    }
    void get_fail(){
        queue<int> q;
        for (int i=0;i<26;i++) if (t[0][i]) q.push(t[0][i]);
        while(!q.empty()) {
            int i=q.front();q.pop();
            for(int j=0;j<26;j++) {
                if (t[i][j]){
                    fail[t[i][j]]=t[fail[i]][j];
                    // d[t[i][j]]+=d[fail[t[i][j]]];
                    q.push(t[i][j]);
                }else
                t[i][j]=t[fail[i]][j];
            }
        }
    }
    void AC_automation(char *x){
        int i=0;
        for(int j=0;x[j];j++) {
            int k=i=t[i][x[j]-'a'];
            while(k){
                if (d[k]>0) w[j]+=d[k];
                // if (d[k]==-1) break;
                k=fail[k];
            }
            // i=t[i][x[j]-'a'];
            // w[j]=d[i];

        }
    }
}T1,T2;

char t[N],s[N];

int main(){
    // freopen("1.cpp","r",stdin);
    scanf("%s",t);
    int n;
    sc(n);
    while(n--){
        scanf("%s",s);
        T1.ins(s);
        int l=strlen(s);
        reverse(s,s+l);
        T2.ins(s);
    }
    T1.get_fail(); T2.get_fail();

    T1.AC_automation(t);

    int l=strlen(t); reverse(t,t+l);

    T2.AC_automation(t);
    LL ans=0;
    for(int i=0;i<l-1;i++) ans+=1ll*T1.w[i]*T2.w[l-i-2];
    cout<<ans;
}


#include<bits/stdc++.h>
#define N 2010
#define INF 0x3f3f3f3f
#define eps 1e-6
#define pi acos(-1.0)
#define mod 998244353
#define P 1000000007
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define bug(x) cerr<<#x<<"      :   "<<x<<endl
#define mem(x) memset(x,0,sizeof x)
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
struct Trie{
    struct node{int fail,cnt,ch[26];}T[N];
    int w[N];
    int tot,root;
    void init(){ tot=root=0;memset(T,0,sizeof(T)); }
    void ins(char* x){
        int o=root,len=strlen(x);
        for(int k=0;k<len;k++){
            int c=x[k]-'a';
            if(!T[o].ch[c]) T[o].ch[c]=++tot;
            o=T[o].ch[c];
        }
        T[o].cnt++;
    }
    void get_fail(){
        queue<int> q;
        for (int i=0;i<26;i++) if (T[0].ch[i]) q.push(T[0].ch[i]);
        while(!q.empty()) {
            int o=q.front();q.pop();
            for(int i=0;i<26;i++) {
                if (T[o].ch[i]){
                    T[T[o].ch[i]].fail=T[T[o].fail].ch[i];
                    q.push(T[o].ch[i]);
                }else
                T[o].ch[i]=T[T[o].fail].ch[i];
            }
        }
    }
    void AC_automation(char *x){
        int o=root,len=strlen(x);
        // bug(len);
        for(int i=0;i<len;i++) {
            int j=o=T[o].ch[x[i]-'a'];
            while(j){
                if (T[j].cnt>0)w[i]+=T[j].cnt;//cout<<i<<"        :          "<<w[i]<<endl;
                // if (T[j].cnt==-1) break;
                // T[j].cnt=-1;
                j=T[j].fail;
            }
        }
    }
}T1,T2;

char t[N],s[N];

int main(){
    scanf("%s",t);
    int n;
    sc(n);
    while(n--){
        scanf("%s",s);
        T1.ins(s);
        int l=strlen(s);
        reverse(s,s+l);
        T2.ins(s);
    }
    T1.get_fail(); T2.get_fail();
    T1.AC_automation(t);

    int l=strlen(t); reverse(t,t+l);

    T2.AC_automation(t);
    LL ans=0;
    for(int i=0;i<l-1;i++) ans+=1ll*T1.w[i]*T2.w[l-i-2];
    cout<<ans;

}


#include<bits/stdc++.h>
#define N 200010
#define INF 0x3f3f3f3f
#define eps 1e-6
#define pi acos(-1.0)
#define mod 998244353
#define P 1000000007
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define bug(x) cerr<<#x<<"      :   "<<x<<endl
#define mem(x) memset(x,0,sizeof x)
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
struct Trie{
    struct node{int fail,cnt,ch[26];}T[N];
    int w[N];
    int tot,root;
    void init(){ tot=root=0;memset(T,0,sizeof(T)); }
    void ins(char* x){
        int o=root,len=strlen(x);
        for(int k=0;k<len;k++){
            int c=x[k]-'a';
            if(!T[o].ch[c]) T[o].ch[c]=++tot;
            o=T[o].ch[c];
        }
        T[o].cnt++;
        // if (o==2){
        //     cout<<"!@!@\n"<<T[2].cnt<<endl;
        // }
    }
    void get_fail(){
        queue<int> q;
        for (int i=0;i<26;i++) if (T[0].ch[i]) q.push(T[0].ch[i]);
        while(!q.empty()) {
            int o=q.front();q.pop();
            for(int i=0;i<26;i++) {
                if (T[o].ch[i]){
                    T[T[o].ch[i]].fail=T[T[o].fail].ch[i];
                    T[T[o].ch[i]].cnt+=T[T[T[o].ch[i]].fail].cnt;
                    // if (o==1) cout<<T[T[o].ch[i]].cnt<<endl;
                    // cout<<T[1].fail<<endl;
                    // cout<<T[2].fail<<endl;
                    q.push(T[o].ch[i]);
                }else
                T[o].ch[i]=T[T[o].fail].ch[i];
            }
        }
    }
    void AC_automation(char *x){
        int o=root,len=strlen(x);
        // for(int i=0,j=0;i<len;i++){
        //     j=T[i].ch[x[i]-'a'];
        //     w[i]=T[j].cnt; cout<<i<<"       :     "<<w[i]<<endl;
        // }
        // // bug(len);
        for(int i=0;i<len;i++) {
            int j=o=T[o].ch[x[i]-'a'];

                if (T[j].cnt>0)w[i]+=T[j].cnt;//cout<<i<<"        :          "<<w[i]<<endl;
                // if (T[j].cnt==-1) break;
                // T[j].cnt=-1;
                j=T[j].fail;

        }
    }
}T1,T2;

char t[N],s[N];

int main(){
    // freopen("1.cpp","r",stdin);
    scanf("%s",t);
    int n;
    sc(n);
    while(n--){
        scanf("%s",s);
        T1.ins(s);
        int l=strlen(s);
        reverse(s,s+l);
        T2.ins(s);
    }
    T1.get_fail(); T2.get_fail();
    // cout<<T1.T[2].fail<<endl;

    T1.AC_automation(t);

    int l=strlen(t); reverse(t,t+l);

    T2.AC_automation(t);
    LL ans=0;
    for(int i=0;i<l-1;i++) ans+=1ll*T1.w[i]*T2.w[l-i-2];
    cout<<ans;

}


#include<bits/stdc++.h>
#define N 200010
#define INF 0x3f3f3f3f
#define eps 1e-6
#define pi acos(-1.0)
#define mod 998244353
#define P 1000000007
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define bug(x) cerr<<#x<<"      :   "<<x<<endl
#define mem(x) memset(x,0,sizeof x)
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
struct Trie{
    struct node{int fail,cnt,ch[26];}T[N];
    int w[N];
    int tot,root;
    void init(){ tot=root=0;memset(T,0,sizeof(T)); }
    void ins(char* x){
        int o=root,len=strlen(x);
        for(int k=0;k<len;k++){
            int c=x[k]-'a';
            if(!T[o].ch[c]) T[o].ch[c]=++tot;
            o=T[o].ch[c];
        }
        T[o].cnt++;
    }
    void get_fail(){
        queue<int> q;
        for (int i=0;i<26;i++) if (T[0].ch[i]) q.push(T[0].ch[i]);
        while(!q.empty()) {
            int o=q.front();q.pop();
            for(int i=0;i<26;i++) {
                if (T[o].ch[i]){
                    T[T[o].ch[i]].fail=T[T[o].fail].ch[i];
                    T[T[o].ch[i]].cnt+=T[T[o].fail].cnt;
                    q.push(T[o].ch[i]);
                }else
                T[o].ch[i]=T[T[o].fail].ch[i];
            }
        }
    }
    void AC_automation(char *x){
        int o=root,len=strlen(x);
        // for(int i=0,j=0;i<len;i++){
        //     j=T[i].ch[x[i]-'a'];
        //     w[i]=T[j].cnt; cout<<i<<"       :     "<<w[i]<<endl;
        // }
        // // bug(len);
        for(int i=0;i<len;i++) {
            int j=o=T[o].ch[x[i]-'a'];

                if (T[j].cnt>0)w[i]+=T[j].cnt;//cout<<i<<"        :          "<<w[i]<<endl;
                // if (T[j].cnt==-1) break;
                // T[j].cnt=-1;
                j=T[j].fail;

        }
    }
}T1,T2;

char t[N],s[N];

int main(){
    freopen("1.cpp","r",stdin);
    scanf("%s",t);
    int n;
    sc(n);
    while(n--){
        scanf("%s",s);
        T1.ins(s);
        int l=strlen(s);
        reverse(s,s+l);
        T2.ins(s);
    }
    T1.get_fail(); T2.get_fail();
    T1.AC_automation(t);

    int l=strlen(t); reverse(t,t+l);

    T2.AC_automation(t);
    LL ans=0;
    for(int i=0;i<l-1;i++) ans+=1ll*T1.w[i]*T2.w[l-i-2];
    cout<<ans;

}


#include<bits/stdc++.h>
#define N 200010
#define INF 0x3f3f3f3f
#define eps 1e-6
#define pi acos(-1.0)
#define mod 998244353
#define P 1000000007
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define bug(x) cerr<<#x<<"      :   "<<x<<endl
#define mem(x) memset(x,0,sizeof x)
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
struct Trie{
    struct node{int fail,cnt,ch[26];}T[N];
    int w[N];
    int tot,root;
    void init(){ tot=root=0;memset(T,0,sizeof(T)); }
    void ins(char* x){
        int o=root,len=strlen(x);
        for(int k=0;k<len;k++){
            int c=x[k]-'a';
            if(!T[o].ch[c]) T[o].ch[c]=++tot;
            o=T[o].ch[c];
        }
        T[o].cnt++;
    }
    void get_fail(){
        queue<int> q;
        for (int i=0;i<26;i++) if (T[0].ch[i]) q.push(T[0].ch[i]);
        while(!q.empty()) {
            int o=q.front();q.pop();
            for(int i=0;i<26;i++) {
                if (T[o].ch[i]){
                    T[T[o].ch[i]].fail=T[T[o].fail].ch[i];
                    q.push(T[o].ch[i]);
                }else
                T[o].ch[i]=T[T[o].fail].ch[i];
            }
        }
    }
    void AC_automation(char *x){
        int o=root,len=strlen(x);
        // bug(len);
        for(int i=0;i<len;i++) {
            int j=o=T[o].ch[x[i]-'a'];
            while(j){
                if (T[j].cnt>0)w[i]+=T[j].cnt;//cout<<i<<"        :          "<<w[i]<<endl;
                // if (T[j].cnt==-1) break;
                // T[j].cnt=-1;
                j=T[j].fail;
            }
        }
    }
}T1,T2;

char t[N],s[N];

int main(){
    scanf("%s",t);
    int n;
    sc(n);
    while(n--){
        scanf("%s",s);
        T1.ins(s);
        int l=strlen(s);
        reverse(s,s+l);
        T2.ins(s);
    }
    T1.get_fail(); T2.get_fail();
    T1.AC_automation(t);

    int l=strlen(t); reverse(t,t+l);

    T2.AC_automation(t);
    LL ans=0;
    for(int i=0;i<l-1;i++) ans+=1ll*T1.w[i]*T2.w[l-i-2];
    cout<<ans;

}


#include<bits/stdc++.h>
#define N 200010
#define INF 0x3f3f3f3f
#define eps 1e-6
#define pi acos(-1.0)
#define mod 998244353
#define P 1000000007
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define bug(x) cerr<<#x<<"      :   "<<x<<endl
#define mem(x) memset(x,0,sizeof x)
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
struct Trie{
    int t[N][26],fail[N],d[N],w[N];
    int tot,root;
    void init(){ tot=root=0;
        memset(fail,0,sizeof fail);
        memset(t,0,sizeof t);
        memset(d,0,sizeof d);
    }
    void ins(char* x){
        int i=0;
        for(int k=0;x[k];k++){
            int c=x[k]-'a';
            if(!t[i][c]) t[i][c]=++tot;
            i=t[i][c];
        }
        d[i]++;
    }
    void get_fail(){
        queue<int> q;
        for (int i=0;i<26;i++) if (t[0][i]) q.push(t[0][i]);
        while(!q.empty()) {
            int i=q.front();q.pop();
            for(int j=0;j<26;j++) {
                if (t[i][j]){
                    fail[t[i][j]]=t[fail[i]][j];
                    d[t[i][j]]+=d[fail[t[i][j]]];
                    // if (o==1) cout<<t[t[i][i]].cnt<<endl;
                    // cout<<t[1].fail<<endl;
                    // cout<<t[2].fail<<endl;
                    q.push(t[i][j]);
                }else
                t[i][j]=t[fail[i]][j];
            }
        }
    }
    void AC_automation(char *x){
        int i=0;
        // for(int i=0,j=0;i<len;i++){
        //     j=t[i][x[i]-'a'];
        //     w[i]=t[j].cnt; cout<<i<<"       :     "<<w[i]<<endl;
        // }
        // // bug(len);
        for(int j=0;x[j];j++) {
            i=t[i][x[j]-'a'];

                // if (t[j].cnt>0)w[i]+=t[j].cnt;//cout<<i<<"        :          "<<w[i]<<endl;
                // if (t[j].cnt==-1) break;
                // t[j].cnt=-1;
            w[j]=d[i];

        }
    }
}T1,T2;

char t[N],s[N];

int main(){
    // freopen("1.cpp","r",stdin);
    scanf("%s",t);
    int n;
    sc(n);
    while(n--){
        scanf("%s",s);
        T1.ins(s);
        int l=strlen(s);
        reverse(s,s+l);
        T2.ins(s);
    }
    T1.get_fail(); T2.get_fail();
    // cout<<T1.t[2].fail<<endl;

    T1.AC_automation(t);

    int l=strlen(t); reverse(t,t+l);

    T2.AC_automation(t);
    LL ans=0;
    for(int i=0;i<l-1;i++) ans+=1ll*T1.w[i]*T2.w[l-i-2];
    cout<<ans;

}


#include<bits/stdc++.h>
#define N 200010
#define INF 0x3f3f3f3f
#define eps 1e-6
#define pi acos(-1.0)
#define mod 998244353
#define P 1000000007
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define bug(x) cerr<<#x<<"      :   "<<x<<endl
#define mem(x) memset(x,0,sizeof x)
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
struct Trie{
    struct node{int fail,cnt,ch[26];}T[N];
    int w[N];
    int tot,root;
    void init(){ tot=root=0;memset(T,0,sizeof(T)); }
    void ins(char* x){
        int o=root,len=strlen(x);
        for(int k=0;k<len;k++){
            int c=x[k]-'a';
            if(!T[o].ch[c]) T[o].ch[c]=++tot;
            o=T[o].ch[c];
        }
        T[o].cnt++;
    }
    void get_fail(){
        queue<int> q;
        for (int i=0;i<26;i++) if (T[0].ch[i]) q.push(T[0].ch[i]);
        while(!q.empty()) {
            int o=q.front();q.pop();
            for(int i=0;i<26;i++) {
                if (T[o].ch[i]){
                    T[T[o].ch[i]].fail=T[T[o].fail].ch[i];
                    T[T[o].ch[i]].cnt+=T[T[o].fail].cnt;
                    q.push(T[o].ch[i]);
                }else
                T[o].ch[i]=T[T[o].fail].ch[i];
            }
        }
    }
    void AC_automation(char *x){
        int o=root,len=strlen(x);
        // for(int i=0,j=0;i<len;i++){
        //     j=T[i].ch[x[i]-'a'];
        //     w[i]=T[j].cnt; cout<<i<<"       :     "<<w[i]<<endl;
        // }
        // // bug(len);
        for(int i=0;i<len;i++) {
            int j=o=T[o].ch[x[i]-'a'];

                if (T[j].cnt>0)w[i]+=T[j].cnt;//cout<<i<<"        :          "<<w[i]<<endl;
                // if (T[j].cnt==-1) break;
                // T[j].cnt=-1;
                j=T[j].fail;

        }
    }
}T1,T2;

char t[N],s[N];

int main(){
    scanf("%s",t);
    int n;
    sc(n);
    while(n--){
        scanf("%s",s);
        T1.ins(s);
        int l=strlen(s);
        reverse(s,s+l);
        T2.ins(s);
    }
    T1.get_fail(); T2.get_fail();
    T1.AC_automation(t);

    int l=strlen(t); reverse(t,t+l);

    T2.AC_automation(t);
    LL ans=0;
    for(int i=0;i<l-1;i++) ans+=1ll*T1.w[i]*T2.w[l-i-2];
    cout<<ans;

}


#include <fstream>
#include <stdio.h>
#include <iostream>
#include <string>
#include <cstring>
#include <set>
#include <algorithm>
#include <time.h>
#include <vector>
#include <map>
#include <queue>

#define isNum(a) (a >= '0' && a <= '9')
#define pb push_back
#define ll long long
const ll INF32 = 1e9;
const ll INF64 = 1e17;
const int RANGE = 1e6 + 5;

const int mod1 = 1000000097;
const int mod2 = 1000415281;
const ll base1 = 241;
const ll base2 = 277;
using namespace std;

template <class T>
void read(T &Val)
{
	T tmp = 0;
    char ch = getchar();
    int flag = 1;
    while (!isNum(ch))
	{
        if (ch == '-')
        	flag = -1;
        ch = getchar();
    }
    while (isNum(ch))
	{
        tmp = tmp*10 + ch - '0';
        ch = getchar();
    }
    Val = flag * tmp;
}

#define TASKIN "input.in"
#define TASKOUT "output.out"
#define TEST2

int n, which = 1;
//char str[RANGE];
//char word[RANGE];

ll strHash[RANGE];
ll value[RANGE];
ll mypow[RANGE];
ll invpow[RANGE];
map <int, map <ll, int> > store;

ll ans;
ll retrieve(int l, int r);
inline void fulfill();
int main()
{
	#ifdef TEST
		freopen(TASKIN, "r", stdin);
 		freopen(TASKOUT, "w", stdout);
		long double time_checking = clock();
	#endif

	fulfill();
	char a; int len = 1;
	while ((a = getchar()) != '\n')
	{
		strHash[len] = (strHash[len-1] + (a * mypow[len]) % mod1) % mod1;
		len++;
	}
	len--;
	read(n);

	for (int i = 0; i < n; i++)
	{
		int ind = 1; ll hash = 0;
		while((a = getchar()) != '\n')
		{
			if (a == EOF) break;

			hash = (hash + (a * mypow[ind]) % mod1) % mod1;
			ind++;
		}

		ind--;
		store[ind][hash]++;
	}

	for (int i = len; i >= 1; i--)
	{
		auto now = store.begin();
		for (; now != store.end(); now++)
		{
			int curlen = now->first;
			if (curlen > len - i + 1) continue;

			ll curhash = retrieve(i, i + curlen - 1);
			if (store[curlen].count(curhash))
			{
				ans = ans + store[curlen][curhash] * value[i + curlen];
				value[i] += store[curlen][curhash];
			}
		}
	}

	cout << ans;

	#ifdef TEST
		cerr << "TIME = " << (long double) (clock() - time_checking)/1000 << endl;
	#endif
	return 0;
}

ll retrieve(int l, int r)
{
	ll tmp = ((strHash[r] - strHash[l-1] + mod1) * invpow[l]) % mod1;
	return tmp;
}

inline void fulfill()
{
	mypow[1] = 1;
	for (int i = 2; i < (int) 3e5; i++)
	mypow[i] = (mypow[i-1] * base1) % mod1;

	int n = mod1 - 2;
	ll tmp = 1, x = base1;
	while (n)
	{
		if (n & 1) tmp = (tmp * x) % mod1;

		n = n >> 1;
		x = (x * x) % mod1;
	}

	invpow[1] = 1;
	for (int i = 2; i < (int) 3e5; i++)
	invpow[i] = (invpow[i-1] * tmp) % mod1;

}


#include <fstream>
#include <stdio.h>
#include <iostream>
#include <string>
#include <cstring>
#include <set>
#include <algorithm>
#include <time.h>
#include <vector>
#include <map>
#include <queue>

#define isNum(a) (a >= '0' && a <= '9')
#define pb push_back
#define ll long long
const ll INF32 = 1e9;
const ll INF64 = 1e17;
const int RANGE = 1e6 + 5;

const int mod1 = 1000000097;
const int mod2 = 1000415281;
const ll base1 = 241;
const ll base2 = 277;
using namespace std;

template <class T>
void read(T &Val)
{
	T tmp = 0;
    char ch = getchar();
    int flag = 1;
    while (!isNum(ch))
	{
        if (ch == '-')
        	flag = -1;
        ch = getchar();
    }
    while (isNum(ch))
	{
        tmp = tmp*10 + ch - '0';
        ch = getchar();
    }
    Val = flag * tmp;
}

#define TASKIN "input.in"
#define TASKOUT "output.out"
#define TEST2

int n, which = 1;
//char str[RANGE];
//char word[RANGE];

ll strHash[RANGE];
ll value[RANGE];
ll pow[RANGE];
ll invpow[RANGE];
map <int, map <ll, int> > store;

ll ans;
ll retrieve(int l, int r);
inline void fulfill();
int main()
{
	#ifdef TEST
		freopen(TASKIN, "r", stdin);
 		freopen(TASKOUT, "w", stdout);
		long double time_checking = clock();
	#endif

	fulfill();
	char a; int len = 1;
	while ((a = getchar()) != '\n')
	{
		strHash[len] = (strHash[len-1] + (a * pow[len]) % mod1) % mod1;
		len++;
	}
	len--;
	read(n);

	for (int i = 0; i < n; i++)
	{
		int ind = 1; ll hash = 0;
		while((a = getchar()) != '\n')
		{
			if (a == EOF) break;

			hash = (hash + (a * pow[ind]) % mod1) % mod1;
			ind++;
		}

		ind--;
		store[ind][hash]++;
	}

	for (int i = len; i >= 1; i--)
	{
		auto now = store.begin();
		for (; now != store.end(); now++)
		{
			int curlen = now->first;
			if (curlen > len - i + 1) continue;

			ll curhash = retrieve(i, i + curlen - 1);
			if (store[curlen].count(curhash))
			{
				ans = ans + store[curlen][curhash] * value[i + curlen];
				value[i] += store[curlen][curhash];
			}
		}
	}

	cout << ans;

	#ifdef TEST
		cerr << "TIME = " << (long double) (clock() - time_checking)/1000 << endl;
	#endif
	return 0;
}

ll retrieve(int l, int r)
{
	ll tmp = ((strHash[r] - strHash[l-1] + mod1) * invpow[l]) % mod1;
	return tmp;
}

inline void fulfill()
{
	pow[1] = 1;
	for (int i = 2; i < (int) 3e5; i++)
	pow[i] = (pow[i-1] * base1) % mod1;

	int n = mod1 - 2;
	ll tmp = 1, x = base1;
	while (n)
	{
		if (n & 1) tmp = (tmp * x) % mod1;

		n = n >> 1;
		x = (x * x) % mod1;
	}

	invpow[1] = 1;
	for (int i = 2; i < (int) 3e5; i++)
	invpow[i] = (invpow[i-1] * tmp) % mod1;

}


#include <fstream>
#include <stdio.h>
#include <iostream>
#include <string>
#include <cstring>
#include <set>
#include <algorithm>
#include <time.h>
#include <vector>
#include <map>
#include <queue>

#define isNum(a) (a >= '0' && a <= '9')
#define pb push_back
#define ll long long
const ll INF32 = 1e9;
const ll INF64 = 1e17;
const int RANGE = 1e6 + 5;

const int mod1 = 1000000097;
const int mod2 = 1000415281;
const ll base1 = 241;
const ll base2 = 277;
using namespace std;

template <class T>
void read(T &Val)
{
	T tmp = 0;
    char ch = getchar();
    int flag = 1;
    while (!isNum(ch))
	{
        if (ch == '-')
        	flag = -1;
        ch = getchar();
    }
    while (isNum(ch))
	{
        tmp = tmp*10 + ch - '0';
        ch = getchar();
    }
    Val = flag * tmp;
}

#define TASKIN "input.in"
#define TASKOUT "output.out"
#define TEST2

int n, which = 1;
//char str[RANGE];
//char word[RANGE];

ll strHash[RANGE];
ll value[RANGE];
ll mypow[RANGE];
ll invpow[RANGE];
map <int, map <ll, int> > store;
int rem_len[RANGE];
int hold[RANGE];
int cnt = 1;

ll ans;
ll retrieve(int l, int r);
inline void fulfill();
int main()
{
	#ifdef TEST
		freopen(TASKIN, "r", stdin);
 		freopen(TASKOUT, "w", stdout);
		long double time_checking = clock();
	#endif

	fulfill();
	char a; int len = 1;
	while ((a = getchar()) != '\n')
	{
		strHash[len] = (strHash[len-1] + (a * mypow[len]) % mod1) % mod1;
		len++;
	}
	len--;
	read(n);

	for (int i = 0; i < n; i++)
	{
		int ind = 1; ll hash = 0;
		while((a = getchar()) != '\n')
		{
			if (a == EOF) break;

			hash = (hash + (a * mypow[ind]) % mod1) % mod1;
			ind++;
		}

		ind--;
		int t;
		if (hold[ind]) t = hold[ind];
		else
		{
			hold[ind] = cnt;
			t = cnt;
			rem_len[t] = ind;
			cnt++;
		}

		store[t][hash]++;
	}

	for (int i = len; i >= 1; i--)
	{
		auto now = store.begin();
		for (; now != store.end(); now++)
		{
			int curlen = rem_len[now->first];
			if (curlen > len - i + 1) continue;

			ll curhash = retrieve(i, i + curlen - 1);
			if (store[now->first].count(curhash))
			{
				ans = ans + store[now->first][curhash] * value[i + curlen];
				value[i] += store[now->first][curhash];
			}
		}
	}

	cout << ans;

	#ifdef TEST
		cerr << "TIME = " << (long double) (clock() - time_checking)/1000 << endl;
	#endif
	return 0;
}

ll retrieve(int l, int r)
{
	ll tmp = ((strHash[r] - strHash[l-1] + mod1) * invpow[l]) % mod1;
	return tmp;
}

inline void fulfill()
{
	mypow[1] = 1;
	for (int i = 2; i < (int) 3e5; i++)
	mypow[i] = (mypow[i-1] * base1) % mod1;

	int n = mod1 - 2;
	ll tmp = 1, x = base1;
	while (n)
	{
		if (n & 1) tmp = (tmp * x) % mod1;

		n = n >> 1;
		x = (x * x) % mod1;
	}

	invpow[1] = 1;
	for (int i = 2; i < (int) 3e5; i++)
	invpow[i] = (invpow[i-1] * tmp) % mod1;

}


#include <fstream>
#include <stdio.h>
#include <iostream>
#include <string>
#include <cstring>
#include <set>
#include <algorithm>
#include <time.h>
#include <vector>
#include <map>
#include <queue>

#define isNum(a) (a >= '0' && a <= '9')
#define pb push_back
#define ll long long
const ll INF32 = 1e9;
const ll INF64 = 1e17;
const int RANGE = 1e6 + 5;

const int mod1 = 1000000097;
const int mod2 = 1000415281;
const ll base1 = 241;
const ll base2 = 277;
using namespace std;

template <class T>
void read(T &Val)
{
	T tmp = 0;
    char ch = getchar();
    int flag = 1;
    while (!isNum(ch))
	{
        if (ch == '-')
        	flag = -1;
        ch = getchar();
    }
    while (isNum(ch))
	{
        tmp = tmp*10 + ch - '0';
        ch = getchar();
    }
    Val = flag * tmp;
}

#define TASKIN "input.in"
#define TASKOUT "output.out"
#define TEST2

int n, which = 1;
//char str[RANGE];
//char word[RANGE];

ll strHash[RANGE];
ll value[RANGE];
ll mypow[RANGE];
ll invpow[RANGE];
map <int, map <ll, int> > store;
int rem_len[RANGE];
int hold[RANGE];
int cnt = 1;

ll ans;
ll retrieve(int l, int r);
inline void fulfill();
int main()
{
	#ifdef TEST
		freopen(TASKIN, "r", stdin);
 		freopen(TASKOUT, "w", stdout);
		long double time_checking = clock();
	#endif

	fulfill();
	char a; int len = 1;
	while ((a = getchar()) != '\n')
	{
		strHash[len] = (strHash[len-1] + (a * mypow[len]) % mod1) % mod1;
		len++;
	}
	len--;
	read(n);

	for (int i = 0; i < n; i++)
	{
		int ind = 1; ll hash = 0;
		while((a = getchar()) != '\n')
		{
			if (a == EOF) break;

			hash = (hash + (a * mypow[ind]) % mod1) % mod1;
			ind++;
		}

		ind--;
		int t;
		if (hold[ind]) t = hold[ind];
		else
		{
			hold[ind] = cnt;
			t = cnt;
			rem_len[t] = ind;
			cnt++;
		}

		store[t][hash]++;
	}

	for (int i = len; i >= 1; i--)
	{
		auto now = store.begin();
		for (; now != store.end(); now++)
		{
			int curlen = rem_len[now->first];
			if (curlen > len - i + 1) continue;

			ll curhash = retrieve(i, i + curlen - 1);
			if (store[curlen].count(curhash))
			{
				ans = ans + store[curlen][curhash] * value[i + curlen];
				value[i] += store[curlen][curhash];
			}
		}
	}

	cout << ans;

	#ifdef TEST
		cerr << "TIME = " << (long double) (clock() - time_checking)/1000 << endl;
	#endif
	return 0;
}

ll retrieve(int l, int r)
{
	ll tmp = ((strHash[r] - strHash[l-1] + mod1) * invpow[l]) % mod1;
	return tmp;
}

inline void fulfill()
{
	mypow[1] = 1;
	for (int i = 2; i < (int) 3e5; i++)
	mypow[i] = (mypow[i-1] * base1) % mod1;

	int n = mod1 - 2;
	ll tmp = 1, x = base1;
	while (n)
	{
		if (n & 1) tmp = (tmp * x) % mod1;

		n = n >> 1;
		x = (x * x) % mod1;
	}

	invpow[1] = 1;
	for (int i = 2; i < (int) 3e5; i++)
	invpow[i] = (invpow[i-1] * tmp) % mod1;

}


#include <fstream>
#include <stdio.h>
#include <iostream>
#include <string>
#include <cstring>
#include <set>
#include <algorithm>
#include <time.h>
#include <vector>
#include <map>
#include <queue>

#define isNum(a) (a >= '0' && a <= '9')
#define pb push_back
#define ll long long
const ll INF32 = 1e9;
const ll INF64 = 1e17;
const int RANGE = 1e6 + 5;

const int mod1 = 1000000097;
const int mod2 = 1000415281;
const ll base1 = 241;
const ll base2 = 277;
using namespace std;

template <class T>
void read(T &Val)
{
	T tmp = 0;
    char ch = getchar();
    int flag = 1;
    while (!isNum(ch))
	{
        if (ch == '-')
        	flag = -1;
        ch = getchar();
    }
    while (isNum(ch))
	{
        tmp = tmp*10 + ch - '0';
        ch = getchar();
    }
    Val = flag * tmp;
}

#define TASKIN "input.in"
#define TASKOUT "output.out"
#define TEST2

int n, which = 1;
//char str[RANGE];
//char word[RANGE];

ll strHash[RANGE];
ll value[RANGE];
ll mypow[RANGE];
ll invpow[RANGE];
map <ll, ll> store[800];
int rem_len[RANGE];
int hold[RANGE];
int cnt = 1;

ll ans;
ll retrieve(int l, int r);
inline void fulfill();
int main()
{
	#ifdef TEST
		freopen(TASKIN, "r", stdin);
 		freopen(TASKOUT, "w", stdout);
		long double time_checking = clock();
	#endif

	fulfill();
	char a; int len = 1;
	while ((a = getchar()) != '\n')
	{
		strHash[len] = (strHash[len-1] + (a * mypow[len]) % mod1) % mod1;
		len++;
	}
	len--;
	read(n);

	for (int i = 0; i < n; i++)
	{
		int ind = 1; ll hash = 0;
		while((a = getchar()) != '\n')
		{
			if (a == EOF) break;

			hash = (hash + (a * mypow[ind]) % mod1) % mod1;
			ind++;
		}

		ind--;
		int t;
		if (hold[ind]) t = hold[ind];
		else
		{
			hold[ind] = cnt;
			t = cnt;
			rem_len[t] = ind;
			cnt++;
		}

		store[t][hash]++;
	}

	for (int i = len; i >= 1; i--)
	{
		for (int now = 1; now < cnt; now++)
		{
			int curlen = rem_len[now];
			if (curlen > len - i + 1) continue;

			ll curhash = retrieve(i, i + curlen - 1);
			if (store[now].count(curhash))
			{
				ans = ans + store[now][curhash] * value[i + curlen];
				value[i] += store[now][curhash];
			}
		}
	}

	cout << ans;

	#ifdef TEST
		cerr << "TIME = " << (long double) (clock() - time_checking)/1000 << endl;
	#endif
	return 0;
}

ll retrieve(int l, int r)
{
	ll tmp = ((strHash[r] - strHash[l-1] + mod1) * invpow[l]) % mod1;
	return tmp;
}

inline void fulfill()
{
	mypow[1] = 1;
	for (int i = 2; i < (int) 3e5; i++)
	mypow[i] = (mypow[i-1] * base1) % mod1;

	int n = mod1 - 2;
	ll tmp = 1, x = base1;
	while (n)
	{
		if (n & 1) tmp = (tmp * x) % mod1;

		n = n >> 1;
		x = (x * x) % mod1;
	}

	invpow[1] = 1;
	for (int i = 2; i < (int) 3e5; i++)
	invpow[i] = (invpow[i-1] * tmp) % mod1;

}


#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

#define MAXN 200013
#define MAXLEN 200100
int N; // size of dictionary
string dict[MAXN];
string text;

#define MAXM 200013
int M; // number of states in the automation
int g[MAXM][26]; // the normal edges in the trie
int f[MAXM]; // failure function
LL out[MAXM]; // output function

long long dp[MAXLEN][2];

int aho_corasick() {
    memset(g, -1, sizeof g);
    memset(out, 0, sizeof out);

    int nodes = 1;

    // build the trie
    for (int i = 0; i < N; i++) {
        string& s = dict[i];
        int cur = 0;

        for (int j = 0; j < s.size(); j++) {
            if (g[cur][s[j] - 'a'] == -1) {
                g[cur][s[j] - 'a'] = nodes++;
            }
            cur = g[cur][s[j] - 'a'];
        }
        out[cur]++;
    }

    for (int ch = 0; ch < 26; ch++) {
        if (g[0][ch] == -1) {
            g[0][ch] = 0;
        }
    }

    // BFS to calculate out and failure functions
    memset(f, -1, sizeof f);
    queue<int> q;
    for (int ch = 0; ch < 26; ch++) {
        if (g[0][ch] != 0) {
            f[g[0][ch]] = 0;
            q.push(g[0][ch]);
        }
    }

    while (!q.empty()) {
        int state = q.front();
        q.pop();

        for (int ch = 0; ch < 26; ch++) {
            if (g[state][ch] == -1) continue;

            int fail = f[state];
            while (g[fail][ch] == -1) {
                fail = f[fail];
            }

            f[g[state][ch]] = g[fail][ch];
            out[g[state][ch]] += out[g[fail][ch]];

            q.push(g[state][ch]);
        }
    }

    return nodes;
}

LL search(int j) {
    // Using the Aho-Corasick automation, search the text.
    int state = 0;
    LL ret = 0;
    for (int i = 0; i < text.length(); i++) {
        char c = text[i];
        while (g[state][c - 'a'] == -1) {
            state = f[state];
        }
        state = g[state][c - 'a'];
        dp[i][j] = out[state];
        ret += out[state];
    }
    // It's that simple!
    return ret;
}

int main() {
    // make I/O faster
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cin >> text >> N;
    for(int i = 0; i < N; i++)
        cin >> dict[i];

    aho_corasick();
    search(0);
    //reverse all the things, to get # of strings beginning at a spot
    reverse(text.begin(), text.end());
    for(int i = 0; i < N; i++)
        reverse(dict[i].begin(), dict[i].end());
    search(1);

    long long ret = 0;
    for(int i = 0; i < text.length() - 1; i++)
        ret += dp[i][0]*dp[text.length() - i - 2][1];
    cout << ret << endl;
    return 0;
    cout << endl;
    for(int i = 0; i < text.length(); i++){
        cout << setw(3) << text[text.length() - 1 - i];
    }
    cout << endl;
    for(int i = 0; i < text.length(); i++){
        cout << setw(3) << dp[i][0];
    }
    cout << endl;
    //reverse
    cout << endl;
    for(int i = 0; i < text.length(); i++){
        cout << setw(3) << dp[text.length() - 1 - i][1];
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

#define MAXN 200013
#define MAXLEN 200100
int N; // size of dictionary
string dict[MAXN];
string text;

#define MAXM 100013
int M; // number of states in the automation
int g[MAXM][26]; // the normal edges in the trie
int f[MAXM]; // failure function
LL out[MAXM]; // output function

int dp[MAXLEN][2];

int aho_corasick() {
    memset(g, -1, sizeof g);
    memset(out, 0, sizeof out);

    int nodes = 1;

    // build the trie
    for (int i = 0; i < N; i++) {
        string& s = dict[i];
        int cur = 0;

        for (int j = 0; j < s.size(); j++) {
            if (g[cur][s[j] - 'a'] == -1) {
                g[cur][s[j] - 'a'] = nodes++;
            }
            cur = g[cur][s[j] - 'a'];
        }
        out[cur]++;
    }

    for (int ch = 0; ch < 26; ch++) {
        if (g[0][ch] == -1) {
            g[0][ch] = 0;
        }
    }

    // BFS to calculate out and failure functions
    memset(f, -1, sizeof f);
    queue<int> q;
    for (int ch = 0; ch < 26; ch++) {
        if (g[0][ch] != 0) {
            f[g[0][ch]] = 0;
            q.push(g[0][ch]);
        }
    }

    while (!q.empty()) {
        int state = q.front();
        q.pop();

        for (int ch = 0; ch < 26; ch++) {
            if (g[state][ch] == -1) continue;

            int fail = f[state];
            while (g[fail][ch] == -1) {
                fail = f[fail];
            }

            f[g[state][ch]] = g[fail][ch];
            out[g[state][ch]] += out[g[fail][ch]];

            q.push(g[state][ch]);
        }
    }

    return nodes;
}

LL search(int j) {
    // Using the Aho-Corasick automation, search the text.
    int state = 0;
    LL ret = 0;
    for (int i = 0; i < text.length(); i++) {
        char c = text[i];
        while (g[state][c - 'a'] == -1) {
            state = f[state];
        }
        state = g[state][c - 'a'];
        dp[i][j] = out[state];
        ret += out[state];
    }
    // It's that simple!
    return ret;
}

int main() {
    // make I/O faster
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cin >> text >> N;
    for(int i = 0; i < N; i++)
        cin >> dict[i];

    aho_corasick();
    search(0);
    //reverse all the things, to get # of strings beginning at a spot
    reverse(text.begin(), text.end());
    for(int i = 0; i < N; i++)
        reverse(dict[i].begin(), dict[i].end());
    search(1);

    int ret = 0;
    for(int i = 0; i < text.length() - 1; i++)
        ret += dp[i][0]*dp[text.length() - i - 2][1];
    cout << ret << endl;
    return 0;
    cout << endl;
    for(int i = 0; i < text.length(); i++){
        cout << setw(3) << text[text.length() - 1 - i];
    }
    cout << endl;
    for(int i = 0; i < text.length(); i++){
        cout << setw(3) << dp[i][0];
    }
    cout << endl;
    //reverse
    cout << endl;
    for(int i = 0; i < text.length(); i++){
        cout << setw(3) << dp[text.length() - 1 - i][1];
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

#define MAXN 200013
#define MAXLEN 200100
int N; // size of dictionary
string dict[MAXN];
string text;

#define MAXM 200013
int M; // number of states in the automation
int g[MAXM][26]; // the normal edges in the trie
int f[MAXM]; // failure function
LL out[MAXM]; // output function

long long dp[MAXLEN][2];

int aho_corasick() {
    memset(g, -1, sizeof g);
    memset(out, 0, sizeof out);

    int nodes = 1;

    // build the trie
    for (int i = 0; i < N; i++) {
        string& s = dict[i];
        int cur = 0;

        for (int j = 0; j < s.size(); j++) {
            if (g[cur][s[j] - 'a'] == -1) {
                g[cur][s[j] - 'a'] = nodes++;
            }
            cur = g[cur][s[j] - 'a'];
        }
        out[cur]++;
    }

    for (int ch = 0; ch < 26; ch++) {
        if (g[0][ch] == -1) {
            g[0][ch] = 0;
        }
    }

    // BFS to calculate out and failure functions
    memset(f, -1, sizeof f);
    queue<int> q;
    for (int ch = 0; ch < 26; ch++) {
        if (g[0][ch] != 0) {
            f[g[0][ch]] = 0;
            q.push(g[0][ch]);
        }
    }

    while (!q.empty()) {
        int state = q.front();
        q.pop();

        for (int ch = 0; ch < 26; ch++) {
            if (g[state][ch] == -1) continue;

            int fail = f[state];
            while (g[fail][ch] == -1) {
                fail = f[fail];
            }

            f[g[state][ch]] = g[fail][ch];
            out[g[state][ch]] += out[g[fail][ch]];

            q.push(g[state][ch]);
        }
    }

    return nodes;
}

LL search(int j) {
    // Using the Aho-Corasick automation, search the text.
    int state = 0;
    LL ret = 0;
    for (int i = 0; i < text.length(); i++) {
        char c = text[i];
        while (g[state][c - 'a'] == -1) {
            state = f[state];
        }
        state = g[state][c - 'a'];
        dp[i][j] = out[state];
        ret += out[state];
    }
    // It's that simple!
    return ret;
}

int main() {
    // make I/O faster
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cin >> text >> N;
    for(int i = 0; i < N; i++)
        cin >> dict[i];

    memset(dp, 0, sizeof dp);
    aho_corasick();
    search(0);
    //reverse all the things, to get # of strings beginning at a spot
    reverse(text.begin(), text.end());
    for(int i = 0; i < N; i++)
        reverse(dict[i].begin(), dict[i].end());
    search(1);

    long long ret = 0;
    for(int i = 0; i < text.length() - 1; i++)
        ret += dp[i][0]*dp[text.length() - i - 2][1];
    cout << ret << endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

#define MAXN 200013
#define MAXLEN 200100
int N; // size of dictionary
string dict[MAXN];
string text;

#define MAXM 200013
int M; // number of states in the automation
int g[MAXM][26]; // the normal edges in the trie
int f[MAXM]; // failure function
LL out[MAXM]; // output function

long long dp[MAXLEN][2];

int aho_corasick() {
    memset(g, -1, sizeof g);
    memset(out, 0, sizeof out);

    int nodes = 1;

    // build the trie
    for (int i = 0; i < N; i++) {
        string& s = dict[i];
        int cur = 0;

        for (int j = 0; j < s.size(); j++) {
            if (g[cur][s[j] - 'a'] == -1) {
                g[cur][s[j] - 'a'] = nodes++;
            }
            cur = g[cur][s[j] - 'a'];
        }
        out[cur]++;
    }

    for (int ch = 0; ch < 26; ch++) {
        if (g[0][ch] == -1) {
            g[0][ch] = 0;
        }
    }

    // BFS to calculate out and failure functions
    memset(f, -1, sizeof f);
    queue<int> q;
    for (int ch = 0; ch < 26; ch++) {
        if (g[0][ch] != 0) {
            f[g[0][ch]] = 0;
            q.push(g[0][ch]);
        }
    }

    while (!q.empty()) {
        int state = q.front();
        q.pop();

        for (int ch = 0; ch < 26; ch++) {
            if (g[state][ch] == -1) continue;

            int fail = f[state];
            while (g[fail][ch] == -1) {
                fail = f[fail];
            }

            f[g[state][ch]] = g[fail][ch];
            out[g[state][ch]] += out[g[fail][ch]];

            q.push(g[state][ch]);
        }
    }

    return nodes;
}

void search(int j) {
    // Using the Aho-Corasick automation, search the text.
    int state = 0;
    for (int i = 0; i < text.length(); i++) {
        char c = text[i];
        while (g[state][c - 'a'] == -1) {
            state = f[state];
        }
        state = g[state][c - 'a'];
        dp[i][j] = out[state];
    }
}

int main() {
    // make I/O faster
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cin >> text >> N;
    for(int i = 0; i < N; i++)
        cin >> dict[i];

    memset(dp, 0, sizeof dp);
    aho_corasick();
    search(0);
    //reverse all the things, to get # of strings beginning at a spot
    reverse(text.begin(), text.end());
    for(int i = 0; i < N; i++)
        reverse(dict[i].begin(), dict[i].end());
    aho_corasick();
    search(1);

    long long ret = 0;
    for(int i = 0; i < text.length() - 1; i++)
        ret += dp[i][0]*dp[text.length() - i - 2][1];
    cout << ret << endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

#define MAXN 200013
#define MAXLEN 200100
int N; // size of dictionary
string dict[MAXN];
string text;

#define MAXM 100013
int M; // number of states in the automation
int g[MAXM][26]; // the normal edges in the trie
int f[MAXM]; // failure function
LL out[MAXM]; // output function

int dp[MAXLEN][2];

int aho_corasick() {
    memset(g, -1, sizeof g);
    memset(out, 0, sizeof out);

    int nodes = 1;

    // build the trie
    for (int i = 0; i < N; i++) {
        string& s = dict[i];
        int cur = 0;

        for (int j = 0; j < s.size(); j++) {
            if (g[cur][s[j] - 'a'] == -1) {
                g[cur][s[j] - 'a'] = nodes++;
            }
            cur = g[cur][s[j] - 'a'];
        }
        out[cur]++;
    }

    for (int ch = 0; ch < 26; ch++) {
        if (g[0][ch] == -1) {
            g[0][ch] = 0;
        }
    }

    // BFS to calculate out and failure functions
    memset(f, -1, sizeof f);
    queue<int> q;
    for (int ch = 0; ch < 26; ch++) {
        if (g[0][ch] != 0) {
            f[g[0][ch]] = 0;
            q.push(g[0][ch]);
        }
    }

    while (!q.empty()) {
        int state = q.front();
        q.pop();

        for (int ch = 0; ch < 26; ch++) {
            if (g[state][ch] == -1) continue;

            int fail = f[state];
            while (g[fail][ch] == -1) {
                fail = f[fail];
            }

            f[g[state][ch]] = g[fail][ch];
            out[g[state][ch]] += out[g[fail][ch]];

            q.push(g[state][ch]);
        }
    }

    return nodes;
}

LL search(int j) {
    // Using the Aho-Corasick automation, search the text.
    int state = 0;
    LL ret = 0;
    for (int i = 0; i < text.length(); i++) {
        char c = text[i];
        while (g[state][c - 'a'] == -1) {
            state = f[state];
        }
        state = g[state][c - 'a'];
        dp[i][j] = out[state];
        ret += out[state];
    }
    // It's that simple!
    return ret;
}

int main() {
    // make I/O faster
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cin >> text >> N;
    for(int i = 0; i < N; i++)
        cin >> dict[i];

    aho_corasick();
    search(0);
    //reverse all the things, to get # of strings beginning at a spot
    reverse(text.begin(), text.end());
    for(int i = 0; i < N; i++)
        reverse(dict[i].begin(), dict[i].end());
    search(1);

    int ret = 0;
    for(int i = 0; i < text.length(); i++)
        ret += dp[i][0]*dp[text.length() - i][1];
    cout << ret << endl;
    return 0;
    cout << endl;
    for(int i = 0; i < text.length(); i++){
        cout << setw(3) << text[text.length() - 1 - i];
    }
    cout << endl;
    for(int i = 0; i < text.length(); i++){
        cout << setw(3) << dp[i][0];
    }
    cout << endl;
    //reverse
//    for(int i = 0; i < text.length(); i++){
//        cout << setw(3) << text[i];
//    }
    cout << endl;
    for(int i = 0; i < text.length(); i++){
        cout << setw(3) << dp[text.length() - 1 - i][1];
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

#define MAXN 200013
#define MAXLEN 200100
int N; // size of dictionary
string dict[MAXN];
string text;

#define MAXM 200013
int M; // number of states in the automation
int g[MAXM][26]; // the normal edges in the trie
int f[MAXM]; // failure function
LL out[MAXM]; // output function

int dp[MAXLEN][2];

int aho_corasick() {
    memset(g, -1, sizeof g);
    memset(out, 0, sizeof out);

    int nodes = 1;

    // build the trie
    for (int i = 0; i < N; i++) {
        string& s = dict[i];
        int cur = 0;

        for (int j = 0; j < s.size(); j++) {
            if (g[cur][s[j] - 'a'] == -1) {
                g[cur][s[j] - 'a'] = nodes++;
            }
            cur = g[cur][s[j] - 'a'];
        }
        out[cur]++;
    }

    for (int ch = 0; ch < 26; ch++) {
        if (g[0][ch] == -1) {
            g[0][ch] = 0;
        }
    }

    // BFS to calculate out and failure functions
    memset(f, -1, sizeof f);
    queue<int> q;
    for (int ch = 0; ch < 26; ch++) {
        if (g[0][ch] != 0) {
            f[g[0][ch]] = 0;
            q.push(g[0][ch]);
        }
    }

    while (!q.empty()) {
        int state = q.front();
        q.pop();

        for (int ch = 0; ch < 26; ch++) {
            if (g[state][ch] == -1) continue;

            int fail = f[state];
            while (g[fail][ch] == -1) {
                fail = f[fail];
            }

            f[g[state][ch]] = g[fail][ch];
            out[g[state][ch]] += out[g[fail][ch]];

            q.push(g[state][ch]);
        }
    }

    return nodes;
}

LL search(int j) {
    // Using the Aho-Corasick automation, search the text.
    int state = 0;
    LL ret = 0;
    for (int i = 0; i < text.length(); i++) {
        char c = text[i];
        while (g[state][c - 'a'] == -1) {
            state = f[state];
        }
        state = g[state][c - 'a'];
        dp[i][j] = out[state];
        ret += out[state];
    }
    // It's that simple!
    return ret;
}

int main() {
    // make I/O faster
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cin >> text >> N;
    for(int i = 0; i < N; i++)
        cin >> dict[i];

    aho_corasick();
    search(0);
    //reverse all the things, to get # of strings beginning at a spot
    reverse(text.begin(), text.end());
    for(int i = 0; i < N; i++)
        reverse(dict[i].begin(), dict[i].end());
    search(1);

    int ret = 0;
    for(int i = 0; i < text.length() - 1; i++)
        ret += dp[i][0]*dp[text.length() - i - 2][1];
    cout << ret << endl;
    return 0;
    cout << endl;
    for(int i = 0; i < text.length(); i++){
        cout << setw(3) << text[text.length() - 1 - i];
    }
    cout << endl;
    for(int i = 0; i < text.length(); i++){
        cout << setw(3) << dp[i][0];
    }
    cout << endl;
    //reverse
    cout << endl;
    for(int i = 0; i < text.length(); i++){
        cout << setw(3) << dp[text.length() - 1 - i][1];
    }
    return 0;
}


#include<bits/stdc++.h>
#define N 200010
using namespace std;
int sz[200001],cnt1[200002],cnt2[200002];
queue<int>q;
struct Aho_Corasick_Automaton{
    int c[N][26],id[N],val[N],fail[N],cnt;
    void ins(string s,int ind){
        int len=s.size();int now=0;
        for(int i=0;i<len;i++){
            int v=s[i]-'a';
            if(!c[now][v])c[now][v]=++cnt;
            now=c[now][v];
        }
        id[now]=ind;
        val[now]++;
    }
    void build(){
        for(int i=0;i<26;i++)if(c[0][i])fail[c[0][i]]=0,q.push(c[0][i]);
        while(!q.empty()){
            int u=q.front();q.pop();
            for(int i=0;i<26;i++)
            if(c[u][i])fail[c[u][i]]=c[fail[u]][i],q.push(c[u][i]);
            else c[u][i]=c[fail[u]][i];
        }
    }
    void query(string s){
        int len=s.size();int now=0;
        for(int i=0;i<len;i++){
            now=c[now][s[i]-'a'];
            for(int t=now;t;t=fail[t])
            {
            	cnt1[i+1]+=val[t];
            	cnt2[i-sz[id[t]]+1]+=val[t];
			}
        }
    }
}AC;
int main()
{
    string t;
    cin>>t;
	int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
    	string s;
    	cin>>s;
    	sz[i]=s.size();
    	AC.ins(s,i);
	}
    AC.build();
	AC.query(t);
	int ans=0,tlen=t.size();
	for(int i=0;i<tlen;i++)
		ans+=cnt1[i]*cnt2[i];
	printf("%d\n",ans);
    return 0;
}


#include<bits/stdc++.h>
#define N 200010
#define int long long
using namespace std;
int sz[200001],cnt1[200002],cnt2[200002];
queue<int>q;
struct Aho_Corasick_Automaton{
    int c[N][26],id[N],val[N],fail[N],cnt;
    void ins(string s,int ind){
        int len=s.size();int now=0;
        for(int i=0;i<len;i++){
            int v=s[i]-'a';
            if(!c[now][v])c[now][v]=++cnt;
            now=c[now][v];
        }
        id[now]=ind;
        val[now]++;
    }
    void build(){
        for(int i=0;i<26;i++)if(c[0][i])fail[c[0][i]]=0,q.push(c[0][i]);
        while(!q.empty()){
            int u=q.front();q.pop();
            for(int i=0;i<26;i++)
            if(c[u][i])fail[c[u][i]]=c[fail[u]][i],q.push(c[u][i]);
            else c[u][i]=c[fail[u]][i];
        }
    }
    void query(string s){
        int len=s.size();int now=0;
        for(int i=0;i<len;i++){
            now=c[now][s[i]-'a'];
            for(int t=now;t;t=fail[t])
            {
            	cnt1[i+1]+=val[t];
            	cnt2[i-sz[id[t]]+1]+=val[t];
			}
        }
    }
}AC;
signed main()
{
    string t;
    cin>>t;
	int n;
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
    {
    	string s;
    	cin>>s;
    	sz[i]=s.size();
    	AC.ins(s,i);
	}
    AC.build();
	AC.query(t);
	int ans=0,tlen=t.size();
	for(int i=0;i<tlen;i++)
		ans+=cnt1[i]*cnt2[i];
	printf("%lld\n",ans);
    return 0;
}


#include<bits/stdc++.h>
#define N 200010
#define int long long
using namespace std;
int sz[200001],cnt1[200002],cnt2[200002];
queue<int>q;
struct Aho_Corasick_Automaton{
    int c[N][26],id[N],val[N],fail[N],cnt;
    void ins(char *s,int ind){
        int len=strlen(s);int now=0;
        for(int i=0;i<len;i++){
            int v=s[i]-'a';
            if(!c[now][v])c[now][v]=++cnt;
            now=c[now][v];
        }
        id[now]=ind;
        val[now]++;
    }
    void build(){
        for(int i=0;i<26;i++)if(c[0][i])fail[c[0][i]]=0,q.push(c[0][i]);
        while(!q.empty()){
            int u=q.front();q.pop();
            for(int i=0;i<26;i++)
            if(c[u][i])fail[c[u][i]]=c[fail[u]][i],q.push(c[u][i]);
            else c[u][i]=c[fail[u]][i];
        }
    }
    void query(char *s){
        int len=strlen(s);int now=0;
        for(int i=0;i<len;i++){
            now=c[now][s[i]-'a'];
            for(int t=now;t;t=fail[t])
            {
            	cnt1[i+1]+=val[t];
            	cnt2[i-sz[id[t]]+1]+=val[t];
			}
        }
    }
}AC;
char t[200001],s[200001];
signed main()
{
	scanf("%s",t);
	int n;
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
    {
    	scanf("%s",s);
    	sz[i]=strlen(s);
    	AC.ins(s,i);
	}
    AC.build();
	AC.query(t);
	int ans=0,tlen=strlen(t);
	for(int i=0;i<tlen;i++)
		ans+=cnt1[i]*cnt2[i];
	printf("%lld\n",ans);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
int c[200001][26],num[200001],fail[200001],in[200001],cnt[2][200001],ncnt=0;
vector<int> rev[200001];
void insert(string s)
{
	int len=s.size(),p=0;
	for(int i=0;i<len;i++)
	{
		int t=s[i]-'a';
		if(!c[p][t])
			c[p][t]=++ncnt;
		p=c[p][t];
	}
	num[p]++;
}
queue<int> q;
void build()
{
	for(int i=0;i<26;i++)
		if(c[0][i])
		{
			rev[0].push_back(c[0][i]);
			q.push(c[0][i]);
		}
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		for(int i=0;i<26;i++)
			if(c[u][i])
			{
				fail[c[u][i]]=c[fail[u]][i];
				rev[c[fail[u]][i]].push_back(c[u][i]);
				in[c[u][i]]++;
				q.push(c[u][i]);
			}
			else
				c[u][i]=c[fail[u]][i];
	}
}
queue<int> tp;
void topo()
{
	for(int i=0;i<=ncnt;i++)
		if(!in[i])
			tp.push(i);
	while(!tp.empty())
	{
		int u=tp.front();
		tp.pop();
		for(vector<int>::iterator iter=rev[u].begin();iter!=rev[u].end();iter++)
		{
			int v=*iter;
			num[v]+=num[u];
			if(--in[v]==0)
				q.push(v);
		}
	}
}
void query(string s,int cntpos)
{
	int len=s.size(),p=0;
	for(int i=0;i<len;i++)
	{
		p=c[p][s[i]-'a'];
		cnt[cntpos][i]=num[p];
	}
}
string s[200001];
int main()
{
	string t;
	cin>>t;
	int n,tlen=t.size();
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		cin>>s[i];
		insert(s[i]);
	}
	build();
	topo();
	query(t,0);
	memset(c,0,sizeof(c));
	memset(num,0,sizeof(num));
	memset(fail,0,sizeof(fail));
	memset(in,0,sizeof(in));
	for(int i=0;i<=ncnt;i++)
		rev[i].clear();
	for(int i=1;i<=n;i++)
	{
		reverse(s[i].begin(),s[i].end());
		insert(s[i]);
	}
	build();
	topo();
	reverse(t.begin(),t.end());
	query(t,1);
	long long ans=0;
	for(int i=0;i<=tlen-2;i++)
		ans+=(long long)cnt[0][i]*cnt[1][tlen-2-i];
	printf("%lld\n",ans);
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
int c[200001][26],num[200001],fail[200001],in[200001],cnt[2][200001],ncnt=0;
vector<int> rev[200001];
void insert(string s)
{
	int len=s.size(),p=0;
	for(int i=0;i<len;i++)
	{
		int t=s[i]-'a';
		if(!c[p][t])
			c[p][t]=++ncnt;
		p=c[p][t];
	}
	num[p]++;
}
queue<int> q;
void build()
{
	for(int i=0;i<26;i++)
		if(c[0][i])
		{
			rev[0].push_back(c[0][i]);
			in[c[0][i]]++;
			q.push(c[0][i]);
		}
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		for(int i=0;i<26;i++)
			if(c[u][i])
			{
				fail[c[u][i]]=c[fail[u]][i];
				rev[c[fail[u]][i]].push_back(c[u][i]);
				in[c[u][i]]++;
				q.push(c[u][i]);
			}
			else
				c[u][i]=c[fail[u]][i];
	}
}
queue<int> tp;
void topo()
{
	for(int i=0;i<=ncnt;i++)
		if(!in[i])
			tp.push(i);
	while(!tp.empty())
	{
		int u=tp.front();
		tp.pop();
		for(vector<int>::iterator iter=rev[u].begin();iter!=rev[u].end();iter++)
		{
			int v=*iter;
			num[v]+=num[u];
			if((--in[v])==0)
				tp.push(v);
		}
	}
}
void query(string s,int cntpos)
{
	int len=s.size(),p=0;
	for(int i=0;i<len;i++)
	{
		p=c[p][s[i]-'a'];
		cnt[cntpos][i]=num[p];
	}
}
string s[200001];
int main()
{
	string t;
	cin>>t;
	int n,tlen=t.size();
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		cin>>s[i];
		insert(s[i]);
	}
	build();
	topo();
	query(t,0);
	memset(c,0,sizeof(c));
	memset(num,0,sizeof(num));
	memset(fail,0,sizeof(fail));
	memset(in,0,sizeof(in));
	for(int i=0;i<=ncnt;i++)
		rev[i].clear();
	ncnt=0;
	for(int i=1;i<=n;i++)
	{
		reverse(s[i].begin(),s[i].end());
		insert(s[i]);
	}
	build();
	topo();
	reverse(t.begin(),t.end());
	query(t,1);
	long long ans=0;
	for(int i=0;i<=tlen-2;i++)
		ans+=(long long)cnt[0][i]*cnt[1][tlen-2-i];
	printf("%lld\n",ans);
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define N 200005

struct Trie{
	int nxt[N][26],fail[N],end[N];
	int root,L;
	int newnode(){
		memset(nxt[L],-1,sizeof nxt[L]);
		end[L]=0;
		return L++;
	}
	void init(){
		L++;
		root=newnode();
	}
	void insert(char buf[]){
		int len=strlen(buf+1);
		int now=root;
		for(int i=1;i<=len;i++){
			if(nxt[now][buf[i]-'a']==-1)
				nxt[now][buf[i]-'a']=newnode();
			now=nxt[now][buf[i]-'a'];
		}
		end[now]++;
	}
	void build(){
		queue<int>q;
		fail[root]=root;
		for(int i=0;i<26;i++)
			if(nxt[root][i]==-1)
				nxt[root][i]=root;
			else {
				fail[nxt[root][i]]=root;
				q.push(nxt[root][i]);
			}
		while(q.size()){
			int now=q.front();
			q.pop();
			for(int i=0;i<26;i++)
				if(nxt[now][i]==-1)
					nxt[now][i]=nxt[fail[now]][i];
				else {
					fail[nxt[now][i]]=nxt[fail[now]][i];
					end[nxt[now][i]]+=end[nxt[fail[now]][i]];
					q.push(nxt[now][i]);
				}
		}
	}
	int sum[N];
	int query(char buf[]){
		int len=strlen(buf+1);
		int now=root;
		for(int i=1;i<=len;i++){
			now=nxt[now][buf[i]-'a'];
			sum[i]+=end[now];
		}
	}
};

char buf[N],t[N];
Trie t1,t2;
int n;
void reserve(char s[]){
	int i=1,j=strlen(s+1);
	while(i<j){
		swap(s[i],s[j]);
		++i,--j;
	}
}

int main(){
	t1.init();
	t2.init();
	scanf("%s%d",t+1,&n);
	for(int i=1;i<=n;i++){
		scanf("%s",buf+1);
		t1.insert(buf);
		reserve(buf);
		t2.insert(buf);
	}
	t1.build();
	t2.build();
	t1.query(t);
	reserve(t);
	t2.query(t);

	int len=strlen(t+1);
	long long ans=0;
	for(int i=0;i<len;i++)
		ans+=(long long)t1.sum[i]*t2.sum[len-i];
	cout<<ans<<'\n';
}


#include<bits/stdc++.h>
using namespace std;
#define N 200005

struct Trie{
	int nxt[N][26],fail[N],end[N];
	int root,L;
	int newnode(){
		memset(nxt[L],-1,sizeof nxt[L]);
		end[L]=0;
		return L++;
	}
	void init(){
		L++;
		root=newnode();
	}
	void insert(char buf[]){
		int len=strlen(buf+1);
		int now=root;
		for(int i=1;i<=len;i++){
			if(nxt[now][buf[i]-'a']==-1)
				nxt[now][buf[i]-'a']=newnode();
			now=nxt[now][buf[i]-'a'];
		}
		end[now]++;
	}
	void build(){
		queue<int>q;
		fail[root]=root;
		for(int i=0;i<26;i++)
			if(nxt[root][i]==-1)
				nxt[root][i]=root;
			else {
				fail[nxt[root][i]]=root;
				q.push(nxt[root][i]);
			}
		while(q.size()){
			int now=q.front();
			q.pop();
			for(int i=0;i<26;i++)
				if(nxt[now][i]==-1)
					nxt[now][i]=nxt[fail[now]][i];
				else {
					fail[nxt[now][i]]=nxt[fail[now]][i];
					q.push(nxt[now][i]);
				}
		}
	}
	int sum[N];
	int query(char buf[]){
		int len=strlen(buf+1);
		int now=root;
		for(int i=1;i<=len;i++){
			now=nxt[now][buf[i]-'a'];
			int tmp=now;
			while(tmp!=root){
				sum[i]+=end[tmp];
				tmp=fail[tmp];
			}
		}
	}
};

char buf[N],t[N];
Trie t1,t2;
int n;
void reserve(char s[]){
	int i=1,j=strlen(s+1);
	while(i<j){
		swap(s[i],s[j]);
		++i,--j;
	}
}

int main(){
	t1.init();
	t2.init();
	scanf("%s%d",t+1,&n);
	for(int i=1;i<=n;i++){
		scanf("%s",buf+1);
		t1.insert(buf);
		reserve(buf);
		t2.insert(buf);
	}
	t1.build();
	t2.build();
	t1.query(t);
	reserve(t);
	t2.query(t);

	int len=strlen(t+1);
	long long ans=0;
	for(int i=0;i<len;i++)
		ans+=(long long)t1.sum[i]*t2.sum[len-i];
	cout<<ans<<'\n';
}


#include <bits/stdc++.h>
using namespace std;

#define FOR(x,n) for(int x=0;x<n;x++)
#define mp make_pair
typedef long long ll;
typedef pair<int,int> iPair;

const int ALPHABETSIZE = 26;
const char ALPHABEGIN = 'a';

vector<string> words;
int beginning[200069];
int ending[200069];

struct Vertex {
  int children[ALPHABETSIZE];
  int parentId = -1;
  char parentChar;
  int suffixLink;
  int outputLink;
  bool isWord = false;
  int wordId = -1;
  int count = 0;

  Vertex() {
    memset(children, -1, ALPHABETSIZE*sizeof(int));
  }
};

class Aho {
public:
  vector<Vertex> trie;

  void buildTrie() {
    FOR(i,words.size()) {
      int curr = 0;
      for(auto c : words[i]) {
	Vertex& currVertex = trie[curr];
	int charIndex = c - ALPHABEGIN;

	if(currVertex.children[charIndex] == -1) {
	  Vertex v = Vertex();
	  v.parentChar = c;
	  v.parentId = curr;
	  currVertex.children[charIndex] = trie.size();
	  trie.push_back(v);
	}

	curr = trie[curr].children[charIndex];
      }

      if(trie[curr].isWord) {
	trie[curr].count++;
      }
      else {
	trie[curr].isWord = true;
	trie[curr].wordId = i;
	trie[curr].count++;
      }
    }
  }

  void buildLinks() {
    deque<int> queue;
    queue.push_back(0);

    while(!queue.empty()) {
      int curr = queue.front();
      Vertex& currVertex = trie[curr];
      queue.pop_front();

      if(curr == 0 || currVertex.parentId == 0) {
	currVertex.suffixLink = 0;
	currVertex.outputLink = 0;
      }
      else {
	char pch = currVertex.parentChar;
	int pCharIndex = pch - ALPHABEGIN;
	int next = trie[currVertex.parentId].suffixLink;

	while(true) {
	  Vertex& nextVertex = trie[next];
	  if(nextVertex.parentId == -1) {
	    if(nextVertex.children[pCharIndex] != -1)
	      currVertex.suffixLink = nextVertex.children[pCharIndex];
	    else
	      currVertex.suffixLink = 0;
	    break;
	  }
	  else if(nextVertex.children[pCharIndex] != -1) {
	    currVertex.suffixLink = nextVertex.children[pCharIndex];
	    break;
	  }

	  next = nextVertex.suffixLink;
	}
      }

      if(trie[currVertex.suffixLink].isWord)
	currVertex.outputLink = currVertex.suffixLink;
      else
	currVertex.outputLink = trie[currVertex.suffixLink].outputLink;

      FOR(i,ALPHABETSIZE) {
	if(currVertex.children[i] != -1)
	  queue.push_back(currVertex.children[i]);
      }
    }
  }

  Aho() {
    trie.push_back(Vertex());  // root

    buildTrie();
    buildLinks();
  }
};

void aho_corasick(string& text, Aho& automaton) {
  int curr = 0;
  FOR(i,text.length()) {
    char c = text[i];
    int charIndex = c - ALPHABEGIN;
    Vertex& currVertex = automaton.trie[curr];

    if(currVertex.children[charIndex] != -1) {
      curr = currVertex.children[charIndex];
    }
    else {
      do {
	curr = automaton.trie[curr].suffixLink;
	Vertex& v = automaton.trie[curr];
	if(v.children[charIndex] != -1) {
	  curr = v.children[charIndex];
	  break;
	}
      } while(curr != 0);
    }

    if(automaton.trie[curr].isWord) {
      Vertex& w = automaton.trie[curr];
      ending[i] += w.count;
      beginning[i - words[w.wordId].length() + 1] += w.count;
    }

    int output = automaton.trie[curr].outputLink;
    while(output != 0) {
      Vertex& o = automaton.trie[output];
      ending[i] += o.count;
      beginning[i - words[o.wordId].length() + 1] += o.count;
      output = automaton.trie[output].outputLink;
    }
  }
}

int main() {
  int n;
  string t;

  cin >> t >> n;
  FOR(i,n) {
    string a;
    cin >> a;
    words.push_back(a);
  }

  Aho automaton = Aho();
  memset(beginning, 0, sizeof beginning);
  memset(ending, 0, sizeof ending);
  aho_corasick(t, automaton);

  ll res = 0;
  FOR(i, t.length() - 1) {
    res += 1ll*ending[i]*beginning[i+1];
  }
  cout << res;
}


#include <bits/stdc++.h>
using namespace std;

#define FOR(x,n) for(int x=0;x<n;x++)
#define mp make_pair
typedef long long ll;
typedef pair<int,int> iPair;

const int ALPHABETSIZE = 26;
const char ALPHABEGIN = 'a';

vector<string> words;
int beginning[200069];
int ending[200069];

struct Vertex {
  int children[ALPHABETSIZE];
  int parentId = -1;
  char parentChar;
  int suffixLink;
  int outputLink;
  bool isWord = false;
  int wordId = -1;
  int count = 0;

  Vertex() {
    memset(children, -1, ALPHABETSIZE*sizeof(int));
  }
};

class Aho {
public:
  vector<Vertex> trie;

  void buildTrie() {
    FOR(i,words.size()) {
      int curr = 0;
      for(auto c : words[i]) {
	Vertex& currVertex = trie[curr];
	int charIndex = c - ALPHABEGIN;

	if(currVertex.children[charIndex] == -1) {
	  Vertex v = Vertex();
	  v.parentChar = c;
	  v.parentId = curr;
	  currVertex.children[charIndex] = trie.size();
	  trie.push_back(v);
	}

	curr = currVertex.children[charIndex];
      }

      if(trie[curr].isWord) {
	trie[curr].count++;
      }
      else {
	trie[curr].isWord = true;
	trie[curr].wordId = i;
	trie[curr].count++;
      }
    }
  }

  void buildLinks() {
    deque<int> queue;
    queue.push_back(0);

    while(!queue.empty()) {
      int curr = queue.front();
      Vertex& currVertex = trie[curr];
      queue.pop_front();

      if(curr == 0 || currVertex.parentId == 0) {
	currVertex.suffixLink = 0;
	currVertex.outputLink = 0;
      }
      else {
	char pch = currVertex.parentChar;
	int pCharIndex = pch - ALPHABEGIN;
	int next = trie[currVertex.parentId].suffixLink;

	while(true) {
	  Vertex& nextVertex = trie[next];
	  if(nextVertex.parentId == -1) {
	    if(nextVertex.children[pCharIndex] != -1)
	      currVertex.suffixLink = nextVertex.children[pCharIndex];
	    else
	      currVertex.suffixLink = 0;
	    break;
	  }
	  else if(nextVertex.children[pCharIndex] != -1) {
	    currVertex.suffixLink = nextVertex.children[pCharIndex];
	    break;
	  }

	  next = nextVertex.suffixLink;
	}
      }

      if(trie[currVertex.suffixLink].isWord)
	currVertex.outputLink = currVertex.suffixLink;
      else
	currVertex.outputLink = trie[currVertex.suffixLink].outputLink;

      FOR(i,ALPHABETSIZE) {
	if(currVertex.children[i] != -1)
	  queue.push_back(currVertex.children[i]);
      }
    }
  }

  Aho() {
    trie.push_back(Vertex());  // root

    buildTrie();
    buildLinks();
  }
};

void aho_corasick(string& text, Aho& automaton) {
  int curr = 0;
  FOR(i,text.length()) {
    char c = text[i];
    int charIndex = c - ALPHABEGIN;
    Vertex& currVertex = automaton.trie[curr];

    if(currVertex.children[charIndex] != -1) {
      curr = currVertex.children[charIndex];
    }
    else {
      do {
	curr = automaton.trie[curr].suffixLink;
	Vertex& v = automaton.trie[curr];
	if(v.children[charIndex] != -1) {
	  curr = v.children[charIndex];
	  break;
	}
      } while(curr != 0);
    }

    if(automaton.trie[curr].isWord) {
      Vertex& w = automaton.trie[curr];
      ending[i] += w.count;
      beginning[i - words[w.wordId].length() + 1] += w.count;
    }

    int output = automaton.trie[curr].outputLink;
    while(output != 0) {
      Vertex& o = automaton.trie[output];
      ending[i] += o.count;
      beginning[i - words[o.wordId].length() + 1] += o.count;
      output = automaton.trie[output].outputLink;
    }
  }
}

int main() {
  int n;
  string t;

  cin >> t >> n;
  FOR(i,n) {
    string a;
    cin >> a;
    words.push_back(a);
  }

  Aho automaton = Aho();
  memset(beginning, 0, sizeof beginning);
  memset(ending, 0, sizeof ending);
  aho_corasick(t, automaton);

  ll res = 0;
  FOR(i, t.length() - 1) {
    res += 1ll*ending[i]*beginning[i+1];
  }
  cout << res;
}


//Wan Hong 3.1
//home
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
typedef long long ll;
typedef std::pair<ll,ll> pll;
typedef std::string str;
#define INF (1ll<<58)
ll read(){ll f=1,x=0;char c=getchar();while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return f*x;}
ll max(ll a,ll b){return a>b?a:b;}
ll min(ll a,ll b){return a<b?a:b;}
bool umax(ll& a,ll b){if(b>a)return a=b,1;return 0;}
bool umin(ll& a,ll b){if(b<a)return a=b,1;return 0;}
/**********/
#define MAXN 400011
struct ACAM
{
    ll t[MAXN][26],val[MAXN],fail[MAXN],vis[MAXN];
    ll cnt=0;
    void insert(char* a,ll n)
    {
        ll u=0;
        for(ll i=1;i<=n;++i)
        {
            ll &v=t[u][a[i]-'a'];
            if(!v)v=++cnt;
            u=v;
        }
        ++val[u];
    }
    void build()
    {
        std::queue<ll>q;
        for(ll i=0;i<26;++i)
            if(t[0][i])q.push(t[0][i]);
        while(!q.empty())
        {
            ll u=q.front();q.pop();
            for(ll i=0;i<26;++i)
            {
                ll &v=t[u][i];
                if(v)fail[v]=t[fail[u]][i],val[v]+=val[fail[v]],q.push(v);
                else v=t[fail[u]][i];
            }
        }
    }
    void Query(char* a,ll n,ll f[])
    {
        for(ll i=0;i<=cnt;++i)vis[i]=0;
        ll u=0;
        for(ll i=1;i<=n;++i)
        {
            u=t[u][a[i]-'a'];
            f[i]=val[u];
        }
    }
}ac,Rac;
ll f1[MAXN],f2[MAXN];
char a[MAXN],b[MAXN];
int main()
{
    scanf("%s",a+1);
    ll n=read(),la=strlen(a+1);
    while(n--)
    {
        scanf("%s",b+1);
        ll lb=strlen(b+1);
        ac.insert(b,lb);
        std::reverse(b+1,b+lb+1);Rac.insert(b,lb);
    }
    ac.build();Rac.build();
    ac.Query(a,la,f1);std::reverse(a+1,a+la+1);Rac.Query(a,la,f2);
    ll ans=0;
    for(ll i=1;i<=la;++i)
	{
		ans+=f1[i]*f2[la-i];
	}
    printf("%lld",ans);
    return 0;
}


#include<bits/stdc++.h>
typedef long long ll;
#define MAXN 200011
struct ACAM
{
    ll t[MAXN][26],val[MAXN],fail[MAXN];
    ll cnt=0;
    void insert(char* a,ll n)
    {
        ll u=0;
        for(ll i=1;i<=n;++i)
        {
            ll &v=t[u][a[i]-'a'];
            if(!v)v=++cnt;
            u=v;
        }
        ++val[u];
    }
    void build()
    {
        std::queue<ll>q;
        for(ll i=0;i<26;++i)
            if(t[0][i])q.push(t[0][i]);
        while(!q.empty())
        {
            ll u=q.front();q.pop();
            for(ll i=0;i<26;++i)
            {
                ll &v=t[u][i];
                if(v)fail[v]=t[fail[u]][i],val[v]+=val[fail[v]],q.push(v);
                else v=t[fail[u]][i];
            }
        }
    }
    void Query(char* a,ll n,ll f[])
    {
        ll u=0;
        for(ll i=1;i<=n;++i)
        {
            u=t[u][a[i]-'a'];
            f[i]=val[u];
        }
    }
}ac,Rac;
ll f1[MAXN],f2[MAXN];
char a[MAXN],b[MAXN];
int main()
{
    scanf("%s",a+1);
    ll n,la=strlen(a+1);std::cin>>n;
    while(n--)
    {
        scanf("%s",b+1);
        ll lb=strlen(b+1);
        ac.insert(b,lb);
        std::reverse(b+1,b+lb+1);Rac.insert(b,lb);
    }
    ac.build();Rac.build();
    ac.Query(a,la,f1);std::reverse(a+1,a+la+1);Rac.Query(a,la,f2);
    ll ans=0;
    for(ll i=1;i<=la;++i)ans+=f1[i]*f2[la-i];
    printf("%lld",ans);
    return 0;
}


//Wan Hong 3.1
//home
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
typedef long long ll;
typedef std::pair<ll,ll> pll;
typedef std::string str;
#define INF (1ll<<58)
ll read(){ll f=1,x=0;char c=getchar();while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return f*x;}
ll max(ll a,ll b){return a>b?a:b;}
ll min(ll a,ll b){return a<b?a:b;}
bool umax(ll& a,ll b){if(b>a)return a=b,1;return 0;}
bool umin(ll& a,ll b){if(b<a)return a=b,1;return 0;}
/**********/
#define MAXN 400011
struct ACAM
{
    ll t[MAXN][26],val[MAXN],fail[MAXN],vis[MAXN];
    ll cnt=0;
    void insert(char* a,ll n)
    {
        ll u=0;
        for(ll i=1;i<=n;++i)
        {
            ll &v=t[u][a[i]-'a'];
            if(!v)v=++cnt;
            u=v;
        }
        ++val[u];
    }
    void build()
    {
        std::queue<ll>q;
        for(ll i=0;i<26;++i)
            if(t[0][i])q.push(t[0][i]);
        while(!q.empty())
        {
            ll u=q.front();q.pop();
            for(ll i=0;i<26;++i)
            {
                ll &v=t[u][i];
                if(v)fail[v]=t[fail[u]][i],val[v]+=val[fail[v]],q.push(v);
                else v=t[fail[u]][i];
            }
        }
    }
    void Query(char* a,ll n,ll f[])
    {
        for(ll i=0;i<=cnt;++i)vis[i]=0;
        ll u=0;
        for(ll i=1;i<=n;++i)
        {
            u=t[u][a[i]-'a'];
            f[i]=val[u];
        }
    }
}ac;
ll f1[MAXN],f2[MAXN];
char a[MAXN],b[MAXN];
int main()
{
    scanf("%s",a+1);
    ll n=read(),la=strlen(a+1);
    while(n--)
    {
        scanf("%s",b+1);
        ll lb=strlen(b+1);
        ac.insert(b,lb);
    }
    ac.build();
    ac.Query(a,la,f1);std::reverse(a+1,a+la+1);ac.Query(a,la,f2);
    ll ans=0;
    for(ll i=1;i<=la;++i)ans+=f1[i]*f2[la-i];
    printf("%lld",ans);
    return 0;
}


//Wan Hong 3.1
//home
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
typedef long long ll;
typedef std::pair<ll,ll> pll;
typedef std::string str;
#define INF (1ll<<58)
ll read(){ll f=1,x=0;char c=getchar();while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return f*x;}
ll max(ll a,ll b){return a>b?a:b;}
ll min(ll a,ll b){return a<b?a:b;}
bool umax(ll& a,ll b){if(b>a)return a=b,1;return 0;}
bool umin(ll& a,ll b){if(b<a)return a=b,1;return 0;}
/**********/
#define MAXN 400011
struct ACAM
{
    ll t[MAXN][26],val[MAXN],fail[MAXN],vis[MAXN];
    ll cnt=0;
    void insert(char* a,ll n)
    {
        ll u=0;
        for(ll i=1;i<=n;++i)
        {
            ll &v=t[u][a[i]-'a'];
            if(!v)v=++cnt;
            u=v;
        }
        ++val[u];
    }
    void build()
    {
        std::queue<ll>q;
        for(ll i=0;i<26;++i)
            if(t[0][i])q.push(t[0][i]);
        while(!q.empty())
        {
            ll u=q.front();q.pop();
            for(ll i=0;i<26;++i)
            {
                ll &v=t[u][i];
                if(v)val[v]+=val[u],fail[v]=t[fail[u]][i],q.push(v);
                else v=t[fail[u]][i];
            }
        }
    }
    void Query(char* a,ll n,ll f[])
    {
        for(ll i=0;i<=cnt;++i)vis[i]=0;
        ll u=0;
        for(ll i=1;i<=n;++i)
        {
            u=t[u][a[i]-'a'];
            f[i]=val[u];
        }
    }
}ac;
ll f1[MAXN],f2[MAXN];
char a[MAXN],b[MAXN];
int main()
{
    scanf("%s",a+1);
    ll n=read(),la=strlen(a+1);
    while(n--)
    {
        scanf("%s",b+1);
        ll lb=strlen(b+1);
        ac.insert(b,lb);
    }
    ac.build();
    ac.Query(a,la,f1);std::reverse(a+1,a+la+1);ac.Query(a,la,f2);
    ll ans=0;
    for(ll i=1;i<=la;++i)ans+=f1[i]*f2[la-i];
    printf("%lld",ans);
    return 0;
}


#include<bits/stdc++.h>
#define N 200005
using namespace std;
typedef long long LL;
const LL mod=2147481811,k=233,inv=138249902;
template <typename T> void read(T &x){
	int f=1;x=0;char c=getchar();
	for (;!isdigit(c);c=getchar()) if (c=='-') f=-f;
	for (; isdigit(c);c=getchar()) x=x*10+c-'0';
	x*=f;
}
unordered_multiset<int> S;
string t,s[N];
int n,f[N],g[N],nxt[N],l[N],L,sz=400,p;
LL ans=0,hs[N],P[N],IP[N];
int Get(int l,int r){
	return IP[l-1]*(hs[r]-hs[l-1]+mod)%mod;
}
int main(){
    ios::sync_with_stdio(0);
	cin>>t;L=t.length();t='*'+t;cin>>n;
	P[0]=IP[0]=1;
	for (int i=1;i<=200000;++i)
		P[i]=P[i-1]*k%mod,IP[i]=IP[i-1]*inv%mod;
	for (int i=1;i<=n;++i) cin>>s[i],l[i]=s[i].length(),s[i]='*'+s[i];
	for (int i=1;i<=n;++i){
		if (l[i]>sz) continue;
		LL Hs=0;
		for (int j=1;j<=l[i];++j)
			Hs=(Hs+P[j-1]*s[i][j])%mod;
		S.insert(Hs);
	}
	for (int i=1;i<=L;++i) hs[i]=(hs[i-1]+P[i-1]*t[i])%mod;
	for (int i=0;i<sz;++i)
		for (int j=1;j+i<=L;++j){
		    p=S.count(Get(j,j+i));
		    f[j]+=p;g[j+i]+=p;
		}
	for (int i=1;i<=n;++i){
		if (l[i]<=sz) continue;
		p=0;
		for (int j=2;j<=l[i];++j){
			for (;p&&s[i][p+1]!=s[i][j];p=nxt[p]);
			if (s[i][p+1]==s[i][j]) ++p; nxt[j]=p;
		}
		p=0;
		for (int j=1;j<=L;++j){
		    for (;p&&s[i][p+1]!=t[j];p=nxt[p]);
		    if (p<l[i]&&s[i][p+1]==t[j]) ++p;
		    if (p==l[i]) ++g[j],++f[j-l[i]+1];
		}
	}
	for (int i=1;i<L;++i) ans+=g[i]*f[i+1];
	cout<<ans<<'\n';
	return 0;
}


#include<bits/stdc++.h>
#define N 200005
using namespace std;
typedef long long LL;
const LL mod=2147481811,k=233,inv=138249902;
template <typename T> void read(T &x){
	int f=1;x=0;char c=getchar();
	for (;!isdigit(c);c=getchar()) if (c=='-') f=-f;
	for (; isdigit(c);c=getchar()) x=x*10+c-'0';
	x*=f;
}
unordered_map<LL,int> S;
unordered_set<LL> SS;
string t,s[N];
int n,f[N],g[N],nxt[N],l[N],L,sz=400,p;
LL ans=0,hs[N],P[N],IP[N],x;
inline LL Get(const int &l,const int &r){
	return IP[l-1]*(hs[r]-hs[l-1]+mod)%mod;
}
int main(){
	ios::sync_with_stdio(0);
	cin>>t;L=t.length();t='*'+t;cin>>n;
	P[0]=IP[0]=1;
	for (int i=1;i<=200000;++i)
		P[i]=P[i-1]*k%mod,IP[i]=IP[i-1]*inv%mod;
	for (int i=1;i<=n;++i) cin>>s[i],l[i]=s[i].length(),s[i]='*'+s[i];
	for (int i=1;i<=n;++i){
		if (l[i]>sz) continue;
		LL Hs=0;
		for (int j=1;j<=l[i];++j)
			Hs=(Hs+P[j-1]*s[i][j])%mod;
		++S[Hs];SS.insert(Hs);
	}
	for (int i=1;i<=L;++i) hs[i]=(hs[i-1]+P[i-1]*t[i])%mod;
	for (int i=0;i<sz;++i)
		for (int j=1;j+i<=L;++j){
			x=Get(j,j+i);if (!SS.count(x)) continue;
			p=S[Get(j,j+i)];f[j]+=p;g[j+i]+=p;
		}
	for (int i=1;i<=n;++i){
		if (l[i]<=sz) continue;
		p=0;
		for (int j=2;j<=l[i];++j){
			for (;p&&s[i][p+1]!=s[i][j];p=nxt[p]);
			if (s[i][p+1]==s[i][j]) ++p; nxt[j]=p;
		}
		p=0;
		for (int j=1;j<=L;++j){
			for (;p&&s[i][p+1]!=t[j];p=nxt[p]);
			if (p<l[i]&&s[i][p+1]==t[j]) ++p;
			if (p==l[i]) ++g[j],++f[j-l[i]+1];
		}
	}
	for (int i=1;i<L;++i) ans+=1ll*g[i]*f[i+1];
	cout<<ans<<'\n';
	return 0;
}