// ~~ icebear love attttt ~~
#include <bits/stdc++.h>
using namespace std;
 
typedef long long ll;
typedef pair<int, int> ii;
typedef pair<int, ii> iii;
 
template<class T>
    bool minimize(T &a, const T &b) {
        if (a > b) return a = b, true;
        return false;
    }
 
template<class T>
    bool maximize(T &a, const T &b) {
        if (a < b) return a = b, true;
        return false;
    }
 
#define FOR(i,a,b) for(int i=(a); i<=(b); ++i)
#define FORR(i,a,b) for(int i=(a); i>=(b); --i)
#define REP(i, n) for(int i=0; i<(n); ++i)
#define RED(i, n) for(int i=(n)-1; i>=0; --i)
#define MASK(i) (1LL << (i))
#define BIT(S, i) (((S) >> (i)) & 1)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define all(x) x.begin(), x.end()
#define task "icebearat"
 
const int MOD = 1e9 + 7;
const int inf = 1e9 + 27092008;
const ll INF = 1e18 + 27092008;
const int N = 2e5 + 5;
int lenStr, numStr, ans[N], cntSame[N];
string pattern;
string str[N];
vector<int> startPos[N], endPos[N];
map<string, int> id;
int cntStart[N];
bool haveStart[N];
 
struct Aho_Corasick {
    const static int MAX_NODE = 26;
    const static char LOWER = 'a';
    struct Node {
        Node *link, *child[MAX_NODE], *go[MAX_NODE], *nearAsk;
        int id;
        vector<Node*> G;
        Node() {
            link = nearAsk = NULL;
            REP(i, MAX_NODE) child[i] = go[i] = NULL;
            id = 0;
        }
    };
 
    Node *root;
    Aho_Corasick() {
        root = new Node();
    }
 
    void add(string &s, int id) {
        Node *p = root;
        for(char c : s) {
            int pos = c - LOWER;
            if (p -> child[pos] == NULL) {
                p -> child[pos] = new Node();
                p -> go[pos] = p -> child[pos];
            }
            p = p -> child[pos];
        }
        p -> id = id;
    }
 
    void BFS() {
        queue<Node*> q;
        REP(pos, MAX_NODE) {
            if (root -> child[pos] == NULL) {
                root -> child[pos] = new Node();
                root -> go[pos] = root -> child[pos];
            }
            q.push(root -> child[pos]);
            root -> G.pb(root -> child[pos]);
            root -> child[pos] -> link = root; 
        }
 
        while(!q.empty()) {
            auto p = q.front(); q.pop();
            REP(pos, MAX_NODE) {
                if (p -> child[pos] == NULL) {
                    p -> go[pos] = p -> link -> go[pos];   
                } else {
                    q.push(p -> child[pos]);
                    p -> child[pos] -> link = p -> link -> go[pos];
                    p -> link -> go[pos] -> G.pb(p -> child[pos]);
                }
            }
        }
    }
 
    void DFS(Node *u, Node *preAsk) {
        u -> nearAsk = preAsk;
        for(auto v : u -> G) {
            if (u -> id == 0) DFS(v, preAsk);
            else DFS(v, u);
        }
    }
 
    void queryPattern(string &s) {
        Node *p = root;
        REP(i, (int)s.size()) {
            int pos = s[i] - LOWER;
            p = p -> go[pos];
            auto tmp = p;
 
            if (tmp -> id == 0) tmp = tmp -> nearAsk;
            while(tmp != NULL) {
                endPos[tmp -> id].pb(i);
                tmp = tmp -> nearAsk;
            }
        }
    }
} aho;
 
ll countGlobal(int i) {
    ll ans = 0;
    for(int pos : startPos[i]) cntStart[pos] -= cntSame[i];
    for(int pos : endPos[i]) ans += 1LL * cntSame[i] * cntStart[pos + 1];
    for(int pos : startPos[i]) cntStart[pos] += cntSame[i];
    return ans;
}
 
ll countInternal(int i) {
    ll ans = 0;
    for(int pos : startPos[i]) haveStart[pos] = true;
    for(int pos : endPos[i]) if (haveStart[pos + 1]) 
        ans += 1LL * cntSame[i] * cntSame[i];
    for(int pos : startPos[i]) haveStart[pos] = false;
    return ans;
}
 
void init(void) {
    cin >> pattern;
    lenStr = (int)pattern.size();
    cin >> numStr;
    FOR(i, 1, numStr) {
        cin >> str[i];
        if (id[str[i]] == 0) id[str[i]] = i;
        cntSame[id[str[i]]]++;
    }
}
 
void process(void) {
    FOR(i, 1, numStr) if (id[str[i]] == i) {
        aho.add(str[i], i);
    }
    aho.BFS();
    aho.DFS(aho.root, NULL);
    aho.queryPattern(pattern);
    FOR(i, 1, numStr) if (id[str[i]] == i) {
        for(int pos : endPos[i]) {
            int start_pos = pos - (int)str[i].size() + 1;
            startPos[i].pb(start_pos);
            cntStart[start_pos] += cntSame[i];
        }
    }
 
    ll ans = 0;
    FOR(i, 1, numStr) if (id[str[i]] == i) {
        ans += countGlobal(i);
        ans += countInternal(i);
    }
    cout << ans << '\n';
}
 
int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    if (fopen(task".inp", "r")) {
        freopen(task".inp", "r", stdin);
        freopen(task".out", "w", stdout);
    }
    int tc = 1;
//    cin >> tc;
    while(tc--) {
        init();
        process();
    }
    return 0;
}