#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <queue>
#include <algorithm>
#define maxn 200021
using namespace std;
int n, t, ch[maxn][26], cnt[maxn], tot, l[maxn], r[maxn];
int fail[maxn];
char s[maxn];
queue<int>q;
vector<string> g;
void insert(string c){
    int len = c.length(), rt = 0;
    for(int i = 0; i < len; i++){
        int x = c[i] - 'a';
        if(!ch[rt][x])ch[rt][x] = ++tot;
        rt = ch[rt][x];
    }
    cnt[rt]++;
}
void build(){
    q.push(0);
    while(!q.empty()){
        int u = q.front();q.pop();
        for(int i = 0; i < 26; i++){
            if(ch[u][i]){
                fail[ch[u][i]] = u == 0 ? 0 : ch[fail[i]][i];
                q.push(ch[u][i]);
            }else ch[u][i] = u == 0 ? 0 : ch[fail[u]][i];
        }
        cnt[u] += cnt[fail[u]];
    }
}

void work(int pos){
    for(auto a: g)insert(a);
    build();
    int len = strlen(s);
    int rt = 0;
    for(int i = 0; i < len; i++){
        rt = ch[rt][s[i] - 'a'];
        if(pos == 1)l[i] = cnt[rt];
        else r[len - i - 1] = cnt[rt];
    }
}

int main(){
    scanf("%s%d", s, &n);
    string a;
    for(int i = 1; i <= n; i++){
        cin>> a;
        g.push_back(a);
    }
    work(1);
    memset(ch, 0, sizeof(ch));
    memset(fail, 0, sizeof(fail));
    memset(cnt, 0, sizeof(cnt));
    tot = 0;
    int len = strlen(s);
    for(int i = 0; i <= (len - 1) / 2; i++)swap(s[i], s[len - i - 1]);
    for(auto b: g)reverse(b.begin(), b.end());
    work(2);

    long long ans = 0;
    for(int i = 0; i < len ;i++){
        ans += l[i] * r[i + 1];
    }
    cout<<ans;
    return 0;
}


#include<bits/stdc++.h>

using namespace std;

const long long MAXN = 5005;
const long long INF = 0x7f3f3f3f;
const long long LINF = 0x1f3f3f3f3f3f3f3f;
const long long MOD = 998244353;
const long long OVER_FLOW = 0xffffffff;

long long n; /**< n个数,m个操作,以model为模 */
long long res1[500010], res2[500010];

struct Trie {
    int next[500010][26], fail[500010], end[500010];
    int root, L;

    int newnode() {
        for (int i = 0; i < 26; i++)
            next[L][i] = -1;
        end[L++] = 0;
        return L - 1;
    }

    void init() {
        L = 0;
        root = newnode();
    }

    void insert(char buf[]) {
        int len = strlen(buf);
        int now = root;
        for (int i = 0; i < len; i++) {
            if (next[now][buf[i] - 'a'] == -1)
                next[now][buf[i] - 'a'] = newnode();
            now = next[now][buf[i] - 'a'];
        }
        end[now]++;
    }

    void build() {
        queue<int> Q;
        fail[root] = root;
        for (int i = 0; i < 26; i++)
            if (next[root][i] == -1)
                next[root][i] = root;
            else {
                fail[next[root][i]] = root;
                Q.push(next[root][i]);
            }
        while (!Q.empty()) {
            int now = Q.front();
            Q.pop();
            for (int i = 0; i < 26; i++)

                if (next[now][i] == -1)
                    next[now][i] = next[fail[now]][i];
                else {
                    fail[next[now][i]] = next[fail[now]][i];
                    Q.push(next[now][i]);
                }
        }
    }

    int query(char buf[], long long res1[]) {
        int len = strlen(buf);
        int now = root;
        int res = 0;
        for (int i = 0; i < len; i++) {
            now = next[now][buf[i] - 'a'];
            int temp = now;
            while (temp != root) {
                res += end[temp];
//                end[temp] = 0;
                res1[i] += end[temp];
                temp = fail[temp];
            }
        }
        return res;
    }

    void debug() {
        for (int i = 0; i < L; i++) {
            printf("id␣=␣%3d,fail␣=␣%3d,end␣=␣%3d,chi␣=␣[", i, fail[i
            ], end[i]);
            for (int j = 0; j < 26; j++)
                printf("%2d", next[i][j]);
            printf("]\n");
        }
    }
};

char buf[1000010], raw[1000010];
Trie ac1, ac2;

int main() {

#ifndef ONLINE_JUDGE
    freopen("testdata.in", "r+", stdin);
    freopen("testdata.out", "w+", stdout);
#endif // ONLINE_JUDGE

#ifndef ONLINE_JUDGE
    auto start_time = clock();
    cerr << setprecision(3) << fixed;
#endif

/*
写代码时请注意：
    1.是否要开Long Long？数组边界处理好了么？
    2.实数精度
    3.下标能从最小值开始就从最小值开始
    5.排序之前不能取模.
    6.0-1子矩阵子序列:前缀和
    7.模拟题注意代码复用.
    8.单个区间问题考虑前缀和,多个区间左右端点拆开,排序,记录端点极值
思考提醒：
    1.最大值和最小值问题可不可以用二分+贪心？
    2.dp
    3.如果规模小的话还能尝试dfs
    4.如果存在等式.转换关系少可以暴力枚举变量,或者考虑从数据大小入手
*/

//    ios::sync_with_stdio(false);
    long long T;
    cin >> raw;
    cin >> T;
    ac1.init(), ac2.init();
    while (T--) {
        cin >> buf;
        ac1.insert(buf);
        reverse(buf, buf + strlen(buf));
        ac2.insert(buf);
    }
    ac1.build(), ac2.build();
//    strcpy(buf, raw);
    long long str_len = strlen(raw);
    ac1.query(raw, res1);
    reverse(raw, raw + str_len);
    ac2.query(raw, res2);
    long long res = 0;
    for (long long i = 0; i < str_len - 1; i++) {
        res += res1[i] * res2[str_len - i - 2];
    }
    cout << res << endl;

#ifndef ONLINE_JUDGE
    auto end_time = clock();
    cerr << "Execution time: " << (end_time - start_time) * (int) 1e3 / CLOCKS_PER_SEC << " ms\n";
#endif

    return 0;

}


#include<bits/stdc++.h>

using namespace std;

const long long MAXN = 5005;
const long long INF = 0x7f3f3f3f;
const long long LINF = 0x1f3f3f3f3f3f3f3f;
const long long MOD = 998244353;
const long long OVER_FLOW = 0xffffffff;

long long n; /**< n个数,m个操作,以model为模 */
long long res1[500010], res2[500010];

struct Trie {
    int next[500010][26], fail[500010], end[500010];
    int root, L;

    int newnode() {
        for (int i = 0; i < 26; i++)
            next[L][i] = -1;
        end[L++] = 0;
        return L - 1;
    }

    void init() {
        L = 0;
        root = newnode();
    }

    void insert(char buf[]) {
        int len = strlen(buf);
        int now = root;
        for (int i = 0; i < len; i++) {
            if (next[now][buf[i] - 'a'] == -1)
                next[now][buf[i] - 'a'] = newnode();
            now = next[now][buf[i] - 'a'];
        }
        end[now]++;
    }

    void build() {
        queue<int> Q;
        fail[root] = root;
        for (int i = 0; i < 26; i++)
            if (next[root][i] == -1)
                next[root][i] = root;
            else {
                fail[next[root][i]] = root;
                Q.push(next[root][i]);
            }
        while (!Q.empty()) {
            int now = Q.front();
            Q.pop();
            end[now]+=end[fail[now]];
            for (int i = 0; i < 26; i++)

                if (next[now][i] == -1)
                    next[now][i] = next[fail[now]][i];
                else {
                    fail[next[now][i]] = next[fail[now]][i];
                    Q.push(next[now][i]);
                }
        }
    }

    int query(char buf[], long long res1[]) {
        int len = strlen(buf);
        int now = root;
        int res = 0;
        for (int i = 0; i < len; i++) {
            now = next[now][buf[i] - 'a'];
            int temp = now;
//            while (temp != root) {
//                res += end[temp];
//                end[temp] = 0;
                res1[i] += end[temp];
//                temp = fail[temp];
//            }
        }
        return res;
    }

    void debug() {
        for (int i = 0; i < L; i++) {
            printf("id␣=␣%3d,fail␣=␣%3d,end␣=␣%3d,chi␣=␣[", i, fail[i
            ], end[i]);
            for (int j = 0; j < 26; j++)
                printf("%2d", next[i][j]);
            printf("]\n");
        }
    }
};

char buf[1000010], raw[1000010];
Trie ac1, ac2;

int main() {

#ifndef ONLINE_JUDGE
    freopen("testdata.in", "r+", stdin);
    freopen("testdata.out", "w+", stdout);
#endif // ONLINE_JUDGE

#ifndef ONLINE_JUDGE
    auto start_time = clock();
    cerr << setprecision(3) << fixed;
#endif

/*
写代码时请注意：
    1.是否要开Long Long？数组边界处理好了么？
    2.实数精度
    3.下标能从最小值开始就从最小值开始
    5.排序之前不能取模.
    6.0-1子矩阵子序列:前缀和
    7.模拟题注意代码复用.
    8.单个区间问题考虑前缀和,多个区间左右端点拆开,排序,记录端点极值
思考提醒：
    1.最大值和最小值问题可不可以用二分+贪心？
    2.dp
    3.如果规模小的话还能尝试dfs
    4.如果存在等式.转换关系少可以暴力枚举变量,或者考虑从数据大小入手
*/

//    ios::sync_with_stdio(false);
    long long T;
//    cin >> raw;
//    cin >> T;
    scanf("%s", raw), scanf("%I64d", &T);
    ac1.init(), ac2.init();
    while (T--) {
//        cin >> buf;
        scanf("%s", buf);
        long long cur_len = strlen(buf);
        ac1.insert(buf);
        reverse(buf, buf + cur_len);
        ac2.insert(buf);
    }
    ac1.build(), ac2.build();
//    strcpy(buf, raw);
    long long str_len = strlen(raw);
    ac1.query(raw, res1);
    reverse(raw, raw + str_len);
    ac2.query(raw, res2);
    long long res = 0;
    for (long long i = 0; i < str_len - 1; i++) {
        res += res1[i] * res2[str_len - i - 2];
    }
//    cout << res << endl;
    printf("%I64d\n", res);

#ifndef ONLINE_JUDGE
    auto end_time = clock();
    cerr << "Execution time: " << (end_time - start_time) * (int) 1e3 / CLOCKS_PER_SEC << " ms\n";
#endif

    return 0;

}


#include<bits/stdc++.h>

using namespace std;

const long long MAXN = 5005;
const long long INF = 0x7f3f3f3f;
const long long LINF = 0x1f3f3f3f3f3f3f3f;
const long long MOD = 998244353;
const long long OVER_FLOW = 0xffffffff;

long long n; /**< n个数,m个操作,以model为模 */
long long res1[500010], res2[500010];

struct Trie {
    int next[500010][26], fail[500010], end[500010];
    int root, L;

    int newnode() {
        for (int i = 0; i < 26; i++)
            next[L][i] = -1;
        end[L++] = 0;
        return L - 1;
    }

    void init() {
        L = 0;
        root = newnode();
    }

    void insert(char buf[]) {
        int len = strlen(buf);
        int now = root;
        for (int i = 0; i < len; i++) {
            if (next[now][buf[i] - 'a'] == -1)
                next[now][buf[i] - 'a'] = newnode();
            now = next[now][buf[i] - 'a'];
        }
        end[now]++;
    }

    void build() {
        queue<int> Q;
        fail[root] = root;
        for (int i = 0; i < 26; i++)
            if (next[root][i] == -1)
                next[root][i] = root;
            else {
                fail[next[root][i]] = root;
                Q.push(next[root][i]);
            }
        while (!Q.empty()) {
            int now = Q.front();
            Q.pop();
            for (int i = 0; i < 26; i++)

                if (next[now][i] == -1)
                    next[now][i] = next[fail[now]][i];
                else {
                    fail[next[now][i]] = next[fail[now]][i];
                    Q.push(next[now][i]);
                }
        }
    }

    int query(char buf[], long long res1[]) {
        int len = strlen(buf);
        int now = root;
        int res = 0;
        for (int i = 0; i < len; i++) {
            now = next[now][buf[i] - 'a'];
            int temp = now;
            while (temp != root) {
                res += end[temp];
//                end[temp] = 0;
                res1[i] += end[temp];
                temp = fail[temp];
            }
        }
        return res;
    }

    void debug() {
        for (int i = 0; i < L; i++) {
            printf("id␣=␣%3d,fail␣=␣%3d,end␣=␣%3d,chi␣=␣[", i, fail[i
            ], end[i]);
            for (int j = 0; j < 26; j++)
                printf("%2d", next[i][j]);
            printf("]\n");
        }
    }
};

char buf[1000010], raw[1000010];
Trie ac1, ac2;

int main() {

#ifndef ONLINE_JUDGE
    freopen("testdata.in", "r+", stdin);
    freopen("testdata.out", "w+", stdout);
#endif // ONLINE_JUDGE

#ifndef ONLINE_JUDGE
    auto start_time = clock();
    cerr << setprecision(3) << fixed;
#endif

/*
写代码时请注意：
    1.是否要开Long Long？数组边界处理好了么？
    2.实数精度
    3.下标能从最小值开始就从最小值开始
    5.排序之前不能取模.
    6.0-1子矩阵子序列:前缀和
    7.模拟题注意代码复用.
    8.单个区间问题考虑前缀和,多个区间左右端点拆开,排序,记录端点极值
思考提醒：
    1.最大值和最小值问题可不可以用二分+贪心？
    2.dp
    3.如果规模小的话还能尝试dfs
    4.如果存在等式.转换关系少可以暴力枚举变量,或者考虑从数据大小入手
*/

//    ios::sync_with_stdio(false);
    long long T;
//    cin >> raw;
//    cin >> T;
    scanf("%s", raw), scanf("%I64d", &T);
    ac1.init(), ac2.init();
    while (T--) {
//        cin >> buf;
        scanf("%s", buf);
        long long cur_len = strlen(buf);
        ac1.insert(buf);
        reverse(buf, buf + cur_len);
        ac2.insert(buf);
    }
    ac1.build(), ac2.build();
//    strcpy(buf, raw);
    long long str_len = strlen(raw);
    ac1.query(raw, res1);
    reverse(raw, raw + str_len);
    ac2.query(raw, res2);
    long long res = 0;
    for (long long i = 0; i < str_len - 1; i++) {
        res += res1[i] * res2[str_len - i - 2];
    }
    cout << res << endl;

#ifndef ONLINE_JUDGE
    auto end_time = clock();
    cerr << "Execution time: " << (end_time - start_time) * (int) 1e3 / CLOCKS_PER_SEC << " ms\n";
#endif

    return 0;

}


#include<bits/stdc++.h>

using namespace std;

const long long MAXN = 5005;
const long long INF = 0x7f3f3f3f;
const long long LINF = 0x1f3f3f3f3f3f3f3f;
const long long MOD = 998244353;
const long long OVER_FLOW = 0xffffffff;

long long n; /**< n个数,m个操作,以model为模 */
long long res1[500010], res2[500010];

struct Trie {
    int next[500010][26], fail[500010], end[500010];
    int root, L;

    int newnode() {
        for (int i = 0; i < 26; i++)
            next[L][i] = -1;
        end[L++] = 0;
        return L - 1;
    }

    void init() {
        L = 0;
        root = newnode();
    }

    void insert(char buf[]) {
        int len = strlen(buf);
        int now = root;
        for (int i = 0; i < len; i++) {
            if (next[now][buf[i] - 'a'] == -1)
                next[now][buf[i] - 'a'] = newnode();
            now = next[now][buf[i] - 'a'];
        }
        end[now]++;
    }

    void build() {
        queue<int> Q;
        fail[root] = root;
        for (int i = 0; i < 26; i++)
            if (next[root][i] == -1)
                next[root][i] = root;
            else {
                fail[next[root][i]] = root;
                Q.push(next[root][i]);
            }
        while (!Q.empty()) {
            int now = Q.front();
            Q.pop();
            for (int i = 0; i < 26; i++)

                if (next[now][i] == -1)
                    next[now][i] = next[fail[now]][i];
                else {
                    fail[next[now][i]] = next[fail[now]][i];
                    Q.push(next[now][i]);
                }
        }
    }

    int query(char buf[], long long res1[]) {
        int len = strlen(buf);
        int now = root;
        int res = 0;
        for (int i = 0; i < len; i++) {
            now = next[now][buf[i] - 'a'];
            int temp = now;
            while (temp != root) {
                res += end[temp];
//                end[temp] = 0;
                res1[i] += end[temp];
                temp = fail[temp];
            }
        }
        return res;
    }

    void debug() {
        for (int i = 0; i < L; i++) {
            printf("id␣=␣%3d,fail␣=␣%3d,end␣=␣%3d,chi␣=␣[", i, fail[i
            ], end[i]);
            for (int j = 0; j < 26; j++)
                printf("%2d", next[i][j]);
            printf("]\n");
        }
    }
};

char buf[1000010], raw[1000010];
Trie ac1, ac2;

int main() {

#ifndef ONLINE_JUDGE
    freopen("testdata.in", "r+", stdin);
    freopen("testdata.out", "w+", stdout);
#endif // ONLINE_JUDGE

#ifndef ONLINE_JUDGE
    auto start_time = clock();
    cerr << setprecision(3) << fixed;
#endif

/*
写代码时请注意：
    1.是否要开Long Long？数组边界处理好了么？
    2.实数精度
    3.下标能从最小值开始就从最小值开始
    5.排序之前不能取模.
    6.0-1子矩阵子序列:前缀和
    7.模拟题注意代码复用.
    8.单个区间问题考虑前缀和,多个区间左右端点拆开,排序,记录端点极值
思考提醒：
    1.最大值和最小值问题可不可以用二分+贪心？
    2.dp
    3.如果规模小的话还能尝试dfs
    4.如果存在等式.转换关系少可以暴力枚举变量,或者考虑从数据大小入手
*/

//    ios::sync_with_stdio(false);
    long long T;
    cin >> raw;
    cin >> T;
    ac1.init(), ac2.init();
    while (T--) {
        cin >> buf;
        long long cur_len=strlen(buf);
        ac1.insert(buf);
        reverse(buf, buf + cur_len);
        ac2.insert(buf);
    }
    ac1.build(), ac2.build();
//    strcpy(buf, raw);
    long long str_len = strlen(raw);
    ac1.query(raw, res1);
    reverse(raw, raw + str_len);
    ac2.query(raw, res2);
    long long res = 0;
    for (long long i = 0; i < str_len - 1; i++) {
        res += res1[i] * res2[str_len - i - 2];
    }
    cout << res << endl;

#ifndef ONLINE_JUDGE
    auto end_time = clock();
    cerr << "Execution time: " << (end_time - start_time) * (int) 1e3 / CLOCKS_PER_SEC << " ms\n";
#endif

    return 0;

}


#include<bits/stdc++.h>

using namespace std;

const long long MAXN = 5005;
const long long INF = 0x7f3f3f3f;
const long long LINF = 0x1f3f3f3f3f3f3f3f;
const long long MOD = 998244353;
const long long OVER_FLOW = 0xffffffff;

long long n; /**< n个数,m个操作,以model为模 */
long long res1[500010], res2[500010];

struct Trie {
    int next[500010][26], fail[500010], end[500010];
    int root, L;

    int newnode() {
        for (int i = 0; i < 26; i++)
            next[L][i] = -1;
        end[L++] = 0;
        return L - 1;
    }

    void init() {
        L = 0;
        root = newnode();
    }

    void insert(char buf[]) {
        int len = strlen(buf);
        int now = root;
        for (int i = 0; i < len; i++) {
            if (next[now][buf[i] - 'a'] == -1)
                next[now][buf[i] - 'a'] = newnode();
            now = next[now][buf[i] - 'a'];
        }
        end[now]++;
    }

    void build() {
        queue<int> Q;
        fail[root] = root;
        for (int i = 0; i < 26; i++)
            if (next[root][i] == -1)
                next[root][i] = root;
            else {
                fail[next[root][i]] = root;
                Q.push(next[root][i]);
            }
        while (!Q.empty()) {
            int now = Q.front();
            Q.pop();
            for (int i = 0; i < 26; i++)

                if (next[now][i] == -1)
                    next[now][i] = next[fail[now]][i];
                else {
                    fail[next[now][i]] = next[fail[now]][i];
                    Q.push(next[now][i]);
                }
        }
    }

    int query(char buf[], long long res1[]) {
        int len = strlen(buf);
        int now = root;
        int res = 0;
        for (int i = 0; i < len; i++) {
            now = next[now][buf[i] - 'a'];
            int temp = now;
            while (temp != root) {
                res += end[temp];
//                end[temp] = 0;
                res1[i] += end[temp];
                temp = fail[temp];
            }
        }
        return res;
    }

    void debug() {
        for (int i = 0; i < L; i++) {
            printf("id␣=␣%3d,fail␣=␣%3d,end␣=␣%3d,chi␣=␣[", i, fail[i
            ], end[i]);
            for (int j = 0; j < 26; j++)
                printf("%2d", next[i][j]);
            printf("]\n");
        }
    }
};

char buf[1000010], raw[1000010];
Trie ac1, ac2;

int main() {

#ifndef ONLINE_JUDGE
    freopen("testdata.in", "r+", stdin);
    freopen("testdata.out", "w+", stdout);
#endif // ONLINE_JUDGE

#ifndef ONLINE_JUDGE
    auto start_time = clock();
    cerr << setprecision(3) << fixed;
#endif

/*
写代码时请注意：
    1.是否要开Long Long？数组边界处理好了么？
    2.实数精度
    3.下标能从最小值开始就从最小值开始
    5.排序之前不能取模.
    6.0-1子矩阵子序列:前缀和
    7.模拟题注意代码复用.
    8.单个区间问题考虑前缀和,多个区间左右端点拆开,排序,记录端点极值
思考提醒：
    1.最大值和最小值问题可不可以用二分+贪心？
    2.dp
    3.如果规模小的话还能尝试dfs
    4.如果存在等式.转换关系少可以暴力枚举变量,或者考虑从数据大小入手
*/

//    ios::sync_with_stdio(false);
    long long T;
//    cin >> raw;
//    cin >> T;
    scanf("%s", raw), scanf("%I64d", &T);
    ac1.init(), ac2.init();
    while (T--) {
//        cin >> buf;
        scanf("%s", buf);
        long long cur_len = strlen(buf);
        ac1.insert(buf);
        reverse(buf, buf + cur_len);
        ac2.insert(buf);
    }
    ac1.build(), ac2.build();
//    strcpy(buf, raw);
    long long str_len = strlen(raw);
    ac1.query(raw, res1);
    reverse(raw, raw + str_len);
    ac2.query(raw, res2);
    long long res = 0;
    for (long long i = 0; i < str_len - 1; i++) {
        res += res1[i] * res2[str_len - i - 2];
    }
//    cout << res << endl;
    printf("I64d\n", res);

#ifndef ONLINE_JUDGE
    auto end_time = clock();
    cerr << "Execution time: " << (end_time - start_time) * (int) 1e3 / CLOCKS_PER_SEC << " ms\n";
#endif

    return 0;

}


#include<bits/stdc++.h>

using namespace std;

const long long MAXN = 5005;
const long long INF = 0x7f3f3f3f;
const long long LINF = 0x1f3f3f3f3f3f3f3f;
const long long MOD = 998244353;
const long long OVER_FLOW = 0xffffffff;

long long n; /**< n个数,m个操作,以model为模 */
long long res1[500010], res2[500010];

struct Trie {
    int next[500010][26], fail[500010], end[500010];
    int root, L;

    int newnode() {
        for (int i = 0; i < 26; i++)
            next[L][i] = -1;
        end[L++] = 0;
        return L - 1;
    }

    void init() {
        L = 0;
        root = newnode();
    }

    void insert(char buf[]) {
        int len = strlen(buf);
        int now = root;
        for (int i = 0; i < len; i++) {
            if (next[now][buf[i] - 'a'] == -1)
                next[now][buf[i] - 'a'] = newnode();
            now = next[now][buf[i] - 'a'];
        }
        end[now]++;
    }

    void build() {
        queue<int> Q;
        fail[root] = root;
        for (int i = 0; i < 26; i++)
            if (next[root][i] == -1)
                next[root][i] = root;
            else {
                fail[next[root][i]] = root;
                Q.push(next[root][i]);
            }
        while (!Q.empty()) {
            int now = Q.front();
            Q.pop();
            for (int i = 0; i < 26; i++)

                if (next[now][i] == -1)
                    next[now][i] = next[fail[now]][i];
                else {
                    fail[next[now][i]] = next[fail[now]][i];
                    Q.push(next[now][i]);
                }
        }
    }

    int query(char buf[], long long res1[]) {
        int len = strlen(buf);
        int now = root;
        int res = 0;
        for (int i = 0; i < len; i++) {
            now = next[now][buf[i] - 'a'];
            int temp = now;
            while (temp != root) {
                res += end[temp];
//                end[temp] = 0;
                res1[i] += end[temp];
                temp = fail[temp];
            }
        }
        return res;
    }

    void debug() {
        for (int i = 0; i < L; i++) {
            printf("id␣=␣%3d,fail␣=␣%3d,end␣=␣%3d,chi␣=␣[", i, fail[i
            ], end[i]);
            for (int j = 0; j < 26; j++)
                printf("%2d", next[i][j]);
            printf("]\n");
        }
    }
};

char buf[1000010], raw[1000010];
Trie ac1, ac2;

int main() {

#ifndef ONLINE_JUDGE
    freopen("testdata.in", "r+", stdin);
    freopen("testdata.out", "w+", stdout);
#endif // ONLINE_JUDGE

#ifndef ONLINE_JUDGE
    auto start_time = clock();
    cerr << setprecision(3) << fixed;
#endif

/*
写代码时请注意：
    1.是否要开Long Long？数组边界处理好了么？
    2.实数精度
    3.下标能从最小值开始就从最小值开始
    5.排序之前不能取模.
    6.0-1子矩阵子序列:前缀和
    7.模拟题注意代码复用.
    8.单个区间问题考虑前缀和,多个区间左右端点拆开,排序,记录端点极值
思考提醒：
    1.最大值和最小值问题可不可以用二分+贪心？
    2.dp
    3.如果规模小的话还能尝试dfs
    4.如果存在等式.转换关系少可以暴力枚举变量,或者考虑从数据大小入手
*/

//    ios::sync_with_stdio(false);
    long long T;
//    cin >> raw;
//    cin >> T;
    scanf("%s", raw), scanf("%I64d", &T);
    ac1.init(), ac2.init();
    while (T--) {
//        cin >> buf;
        scanf("%s", buf);
        long long cur_len = strlen(buf);
        ac1.insert(buf);
        reverse(buf, buf + cur_len);
        ac2.insert(buf);
    }
    ac1.build(), ac2.build();
//    strcpy(buf, raw);
    long long str_len = strlen(raw);
    ac1.query(raw, res1);
    reverse(raw, raw + str_len);
    ac2.query(raw, res2);
    long long res = 0;
    for (long long i = 0; i < str_len - 1; i++) {
        res += res1[i] * res2[str_len - i - 2];
    }
//    cout << res << endl;
    printf("%I64d\n", res);

#ifndef ONLINE_JUDGE
    auto end_time = clock();
    cerr << "Execution time: " << (end_time - start_time) * (int) 1e3 / CLOCKS_PER_SEC << " ms\n";
#endif

    return 0;

}


#include<bits/stdc++.h>

using namespace std;

const long long MAXN = 5005;
const long long INF = 0x7f3f3f3f;
const long long LINF = 0x1f3f3f3f3f3f3f3f;
const long long MOD = 998244353;
const long long OVER_FLOW = 0xffffffff;

long long n; /**< n个数,m个操作,以model为模 */
long long res1[500010], res2[500010];

struct Trie {
    int next[500010][26], fail[500010], end[500010];
    int root, L;

    int newnode() {
        for (int i = 0; i < 26; i++)
            next[L][i] = -1;
        end[L++] = 0;
        return L - 1;
    }

    void init() {
        L = 0;
        root = newnode();
    }

    void insert(char buf[]) {
        int len = strlen(buf);
        int now = root;
        for (int i = 0; i < len; i++) {
            if (next[now][buf[i] - 'a'] == -1)
                next[now][buf[i] - 'a'] = newnode();
            now = next[now][buf[i] - 'a'];
        }
        end[now]++;
    }

    void build() {
        queue<int> Q;
        fail[root] = root;
        for (int i = 0; i < 26; i++)
            if (next[root][i] == -1)
                next[root][i] = root;
            else {
                fail[next[root][i]] = root;
                Q.push(next[root][i]);
            }
        while (!Q.empty()) {
            int now = Q.front();
            Q.pop();
            for (int i = 0; i < 26; i++)

                if (next[now][i] == -1)
                    next[now][i] = next[fail[now]][i];
                else {
                    fail[next[now][i]] = next[fail[now]][i];
                    Q.push(next[now][i]);
                }
        }
    }

    int query(char buf[], long long res1[]) {
        int len = strlen(buf);
        int now = root;
        int res = 0;
        for (int i = 0; i < len; i++) {
            now = next[now][buf[i] - 'a'];
            int temp = now;
            while (temp != root) {
                res += end[temp];
//                end[temp] = 0;
                res1[i] += end[temp];
                temp = fail[temp];
            }
        }
        return res;
    }

    void debug() {
        for (int i = 0; i < L; i++) {
            printf("id␣=␣%3d,fail␣=␣%3d,end␣=␣%3d,chi␣=␣[", i, fail[i
            ], end[i]);
            for (int j = 0; j < 26; j++)
                printf("%2d", next[i][j]);
            printf("]\n");
        }
    }
};

char buf[1000010], raw[1000010];
Trie ac1, ac2;

int main() {

#ifndef ONLINE_JUDGE
    freopen("testdata.in", "r+", stdin);
    freopen("testdata.out", "w+", stdout);
#endif // ONLINE_JUDGE

#ifndef ONLINE_JUDGE
    auto start_time = clock();
    cerr << setprecision(3) << fixed;
#endif

/*
写代码时请注意：
    1.是否要开Long Long？数组边界处理好了么？
    2.实数精度
    3.下标能从最小值开始就从最小值开始
    5.排序之前不能取模.
    6.0-1子矩阵子序列:前缀和
    7.模拟题注意代码复用.
    8.单个区间问题考虑前缀和,多个区间左右端点拆开,排序,记录端点极值
思考提醒：
    1.最大值和最小值问题可不可以用二分+贪心？
    2.dp
    3.如果规模小的话还能尝试dfs
    4.如果存在等式.转换关系少可以暴力枚举变量,或者考虑从数据大小入手
*/

//    ios::sync_with_stdio(false);
    long long T;
    cin >> raw;
    cin >> T;
    ac1.init(), ac2.init();
    while (T--) {
        cin >> buf;
        ac1.insert(buf);
        reverse(buf, buf + strlen(buf));
        ac2.insert(buf);
    }
    ac1.build(), ac2.build();
    strcpy(buf, raw);
    long long str_len = strlen(buf);
    ac1.query(buf,res1);
    reverse(buf, buf + str_len);
    ac2.query(buf,res2);
    long long res = 0;
    for (long long i = 0; i < str_len - 1; i++) {
        res += res1[i] * res2[str_len - i - 2];
    }
    cout << res << endl;

#ifndef ONLINE_JUDGE
    auto end_time = clock();
    cerr << "Execution time: " << (end_time - start_time) * (int) 1e3 / CLOCKS_PER_SEC << " ms\n";
#endif

    return 0;

}


#include <bits/stdc++.h>
#define maxn 700005

using namespace std;

typedef long long ll;

int N,M,T1[maxn],T2[maxn],salv1[maxn],salv2[maxn],L,men[maxn],subcad1[maxn],subcad2[maxn];
ll sol;
char cad[maxn],cad1[maxn];

char s[maxn];
int SA[maxn],wa[maxn], wb[maxn], we[maxn], wv[maxn],S[maxn],A[maxn];
void Sufix_Array(char *cad,int *SA,int N){
	N++;
	int i, j, p, *x = wa, *y = wb, range = 256;
	memset(we, 0, range * sizeof(int));
	for (i = 0; i < N; i++)
		we[ x[i] = cad[i] ]++;
	for (i = 1; i < range; i++) we[i] += we[ i-1 ];
	for (i = N - 1; i >= 0; i--)
		SA[ --we[ x[i] ] ] = i;
	for (j = p = 1; p < N; j <<= 1, range = p){
		for (p = 0, i = N - j; i < N; y[p++] = i , i++) ;
		for (i = 0; i < N; i++)
			if (SA[i] >= j) y[p++] = SA[i] - j;
		for (i = 0; i < N; i++)
			wv[i] = x[ y[i] ];
		memset(we, 0, range * sizeof(int));
		for (i = 0; i< N; i++)
			we[ wv[i] ]++;
		for (i = 1; i < range; i++) we[i] += we[i-1];
		for (i = N-1; i >= 0; i--) SA[--we[wv[i]]] = y[i];
		swap(x, y); x[SA[0]] = 0;
		for (p = i = 1; i < N; i++)
			if(y[SA[i]] == y[SA[i-1]] && y[SA[i]+j] == y[SA[i-1]+j])
				x[SA[i]] = p - 1; else x[SA[i]] = p++;
	}
	N--;
}

int rank1[maxn], LCP [maxn];
void FindLCP(char *cad, int *SA, int N){
	int i, j, k;
	for (i = 1; i <= N; i++)
		rank1[ SA[i] ] = i;
	for (k = i = 0; i < N; LCP [rank1[i++]] = k)
		for (k ? k-- : 0,j = SA[rank1[i]-1]; cad[i + k] == cad[j + k];
				k++);
}

void solve(char *cad,int subcad[],int T[]){

    int ini,fin;

    Sufix_Array(cad,SA,L);

  /*  for(int i=0;i<L;i++)
        cout << cad+SA[i] << " " << subcad[SA[i]] << "\n";
*/
    FindLCP(cad,SA,L);

    for(int i=2;i<=L;i++){
        int pos = i-1;
        int orig = LCP[i];

        if(subcad[SA[i]]) LCP[i] = min(LCP[i] , subcad[SA[i]] );

        while(pos && LCP[pos]>=LCP[i])
             pos = men[pos];
        men[i] = pos;

        if(subcad[SA[i]] && orig>=subcad[SA[i]]){
            ini = men[i];
            fin = i;
            T[ini]++;
            T[fin]--;
        }
    }
   fill(men,men+L+1,0);
}

int main()
{
    cin.tie(0);
    ios_base::sync_with_stdio(0);
    #ifdef acm
    freopen("a.in","r",stdin);
    #endif // acm

    cin >> cad;

    cin >> M;

    L = strlen(cad);
    int L1 = L;

    cad[L++]='{';

    for(int i=1;i<=M;i++){
        cin >> cad1;

        strcat(cad+L,cad1);
        subcad1[L]=strlen(cad1);
        L +=strlen(cad1);
        cad[L++]='}';
    }

    solve(cad,subcad1,T1);

    for(int i=1;i<=L;i++){
        T1[i]+=T1[i-1];
        salv1[SA[i]] = T1[i];
    }

    for(int i=0;i<L;i++)
        if(subcad1[i])
           subcad2[L-i-subcad1[i]] = subcad1[i];

    reverse(cad,cad+L);

    solve(cad,subcad2,T2);

    for(int i=1;i<=L;i++){
        T2[i]+=T2[i-1];
        salv2[L-SA[i]-1] = T2[i];
    }

    for(int i=1;i<L1;i++)
        sol+=(ll)salv2[i-1]*salv1[i];

    cout << sol << "\n";

}


#include <bits/stdc++.h>
#define maxn 700005

using namespace std;

typedef long long ll;

int N,M,T1[maxn],T2[maxn],salv1[maxn],salv2[maxn],L,men[maxn],subcad1[maxn],subcad2[maxn];
ll sol;
char cad[maxn],cad1[maxn];

char s[maxn];
int SA[maxn],wa[maxn], wb[maxn], we[maxn], wv[maxn],S[maxn],A[maxn];
void Sufix_Array(char *cad,int *SA,int N){
	N++;
	int i, j, p, *x = wa, *y = wb, range = 256;
	memset(we, 0, range * sizeof(int));
	for (i = 0; i < N; i++)
		we[ x[i] = cad[i] ]++;
	for (i = 1; i < range; i++) we[i] += we[ i-1 ];
	for (i = N - 1; i >= 0; i--)
		SA[ --we[ x[i] ] ] = i;
	for (j = p = 1; p < N; j <<= 1, range = p){
		for (p = 0, i = N - j; i < N; y[p++] = i , i++) ;
		for (i = 0; i < N; i++)
			if (SA[i] >= j) y[p++] = SA[i] - j;
		for (i = 0; i < N; i++)
			wv[i] = x[ y[i] ];
		memset(we, 0, range * sizeof(int));
		for (i = 0; i< N; i++)
			we[ wv[i] ]++;
		for (i = 1; i < range; i++) we[i] += we[i-1];
		for (i = N-1; i >= 0; i--) SA[--we[wv[i]]] = y[i];
		swap(x, y); x[SA[0]] = 0;
		for (p = i = 1; i < N; i++)
			if(y[SA[i]] == y[SA[i-1]] && y[SA[i]+j] == y[SA[i-1]+j])
				x[SA[i]] = p - 1; else x[SA[i]] = p++;
	}
	N--;
}

int rank1[maxn], LCP [maxn];
void FindLCP(char *cad, int *SA, int N){
	int i, j, k;
	for (i = 1; i <= N; i++)
		rank1[ SA[i] ] = i;
	for (k = i = 0; i < N; LCP [rank1[i++]] = k)
		for (k ? k-- : 0,j = SA[rank1[i]-1]; cad[i + k] == cad[j + k];
				k++);
}

void solve(char *cad,int subcad[],int T[]){

    int ini,fin;

    Sufix_Array(cad,SA,L);

  /*  for(int i=0;i<L;i++)
        cout << cad+SA[i] << " " << subcad[SA[i]] << "\n";
*/
    FindLCP(cad,SA,L);

    for(int i=2;i<=L;i++){
        int pos = i-1;
        int orig = LCP[i];

        if(subcad[SA[i]]) LCP[i] = min(LCP[i] , subcad[SA[i]] );

        while(pos && LCP[pos]>=LCP[i])
             pos = men[pos];
        men[i] = pos;

        if(subcad[SA[i]] && orig>=subcad[SA[i]]){
            ini = men[i];
            fin = i;
            T[ini]++;
            T[fin]--;
        }
    }
   fill(men,men+L+1,0);
}

int main()
{
    cin.tie(0);
    ios_base::sync_with_stdio(0);
    #ifdef acm
    freopen("a.in","r",stdin);
    #endif // acm

    cin >> cad;

    cin >> M;

    L = strlen(cad);
    int L1 = L;

    cad[L++]='{';

    for(int i=1;i<=M;i++){
        cin >> cad1;

        strcat(cad+L,cad1);
        subcad1[L]=strlen(cad1);
        L = strlen(cad);
        cad[L++]='}';
    }

    solve(cad,subcad1,T1);

    for(int i=1;i<=L;i++){
        T1[i]+=T1[i-1];
        salv1[SA[i]] = T1[i];
    }

    for(int i=0;i<L;i++)
        if(subcad1[i])
           subcad2[L-i-subcad1[i]] = subcad1[i];

    reverse(cad,cad+L);

    solve(cad,subcad2,T2);

    for(int i=1;i<=L;i++){
        T2[i]+=T2[i-1];
        salv2[L-SA[i]-1] = T2[i];
    }

    for(int i=1;i<L1;i++)
        sol+=(ll)salv2[i-1]*salv1[i];

    cout << sol << "\n";

}


#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int maxm=2e5+10;
int trie1[maxm][27],cntword1[maxm],flag1[maxm],fail1[maxm],last1[maxm],ed[maxm],st[maxm];
int trie2[maxm][27],cntword2[maxm],flag2[maxm],fail2[maxm],last2[maxm];
int cnt1,cnt2;
char s[maxm],t[maxm],re[maxm],rr[maxm];
void insert(char ss[],int len)
{
	int rt=0;
	//int len=strlen(ss+1);
	for(int i=1;i<=len;i++)
	{
		int nxt=ss[i]-'a';
		if(!trie1[rt][nxt])
			trie1[rt][nxt]=++cnt1;
		rt=trie1[rt][nxt];
	}
	flag1[rt]++;
}
void getfail()
{
	queue<int> q;
	for(int i=0;i<26;i++)
	{
		if(trie1[0][i])
		{
			fail1[trie1[0][i]]=0;
			q.push(trie1[0][i]);
		}
	}
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		//flag1[now]+=flag1[last1[now]];
		for(int i=0;i<26;i++)
		{
			if(trie1[now][i])
			{
				fail1[trie1[now][i]]=trie1[fail1[now]][i];
				last1[trie1[now][i]]=flag1[fail1[trie1[now][i]]]?fail1[trie1[now][i]]:last1[fail1[trie1[now][i]]];
				q.push(trie1[now][i]);
			}
			else
				trie1[now][i]=trie1[fail1[now]][i];
		}
	}
}
/*#define id now
#define last1 fail1
#define last2 fail2*/
void query(char ss[])
{
	int now=0,ans=0;
	int len=strlen(ss+1);
	for(int i=1;i<=len;i++)
	{
		now=trie1[now][ss[i]-'a'];
		int id=flag1[now]?now:last1[now];
		while(id)
		{
			ed[i]+=flag1[id];
			id=last1[id];
		}
		//ed[i]+=flag1[now];
	}
}
void insert2(char ss[],int len)
{
	int rt=0;
	//int len=strlen(ss+1);
	for(int i=1;i<=len;i++)
	{
		int nxt=ss[i]-'a';
		if(!trie2[rt][nxt])
			trie2[rt][nxt]=++cnt2;
		rt=trie2[rt][nxt];
	}
	flag2[rt]++;
}
void getfail2()
{
	queue<int> q;
	for(int i=0;i<26;i++)
	{
		if(trie2[0][i])
		{
			fail2[trie2[0][i]]=0;
			q.push(trie2[0][i]);
		}
	}
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		//flag2[now]+=flag2[last2[now]];
		for(int i=0;i<26;i++)
		{
			if(trie2[now][i])
			{
				fail2[trie2[now][i]]=trie2[fail2[now]][i];
				last2[trie2[now][i]]=flag2[fail2[trie2[now][i]]]?fail2[trie2[now][i]]:last2[fail2[trie2[now][i]]];
				q.push(trie2[now][i]);
			}
			else
				trie2[now][i]=trie2[fail2[now]][i];
		}
	}
}
void query2(char ss[])
{
	int now=0,ans=0;
	int len=strlen(ss+1);
	for(int i=1;i<=len;i++)
	{
		now=trie2[now][ss[i]-'a'];
		int id=flag2[now]?now:last2[now];
		while(id)
		{
			st[i]+=flag2[id];
			id=last2[id];
		}
		//st[i]+=flag2[now];
	}
}
int main()
{
	scanf("%s",s+1);
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",t+1);
		int len=strlen(t+1);
		insert(t,len);
		for(int i=1;i<=len;i++)
		{
			re[i]=t[len-i+1];
		}
		insert2(re,len);
	}
	getfail();
	query(s);
	getfail2();
	int len=strlen(s+1);
	for(int i=1;i<=len;i++)
	{
		rr[i]=s[len-i+1];
	}
	query2(rr);
	ll ans=0;
	for(int i=1;i<=len;i++)
	{
		ans=ans+1ll*ed[i]*st[len-i];
	}
	printf("%I64d\n",ans);
	return 0;
}


#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int maxm=2e5+10;
int trie1[maxm][27],cntword1[maxm],flag1[maxm],fail1[maxm],last1[maxm],ed[maxm],st[maxm];
int trie2[maxm][27],cntword2[maxm],flag2[maxm],fail2[maxm],last2[maxm];
int cnt1,cnt2;
char s[maxm],t[maxm],re[maxm],rr[maxm];
void insert(char ss[],int len)
{
	int rt=0;
	//int len=strlen(ss+1);
	for(int i=0;i<len;i++)
	{
		int nxt=ss[i]-'a';
		if(!trie1[rt][nxt])
			trie1[rt][nxt]=++cnt1;
		rt=trie1[rt][nxt];
	}
	flag1[rt]++;
}
void getfail()
{
	queue<int> q;
	for(int i=0;i<26;i++)
	{
		if(trie1[0][i])
		{
			fail1[trie1[0][i]]=0;
			q.push(trie1[0][i]);
		}
	}
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		//flag1[now]+=flag1[last1[now]];
		for(int i=0;i<26;i++)
		{
			if(trie1[now][i])
			{
				fail1[trie1[now][i]]=trie1[fail1[now]][i];
				last1[trie1[now][i]]=flag1[fail1[trie1[now][i]]]?fail1[trie1[now][i]]:last1[fail1[trie1[now][i]]];
				q.push(trie1[now][i]);
			}
			else
				trie1[now][i]=trie1[fail1[now]][i];
		}
	}
}
/*#define id now
#define last1 fail1
#define last2 fail2*/
void query(char ss[])
{
	int now=0,ans=0;
	int len=strlen(ss);
	for(int i=0;i<len;i++)
	{
		now=trie1[now][ss[i]-'a'];
		int id=flag1[now]?now:last1[now];
		while(id)
		{
			ed[i]+=flag1[id];
			id=last1[id];
		}
		//ed[i]+=flag1[now];
	}
}
void insert2(char ss[],int len)
{
	int rt=0;
	//int len=strlen(ss+1);
	for(int i=0;i<len;i++)
	{
		int nxt=ss[i]-'a';
		if(!trie2[rt][nxt])
			trie2[rt][nxt]=++cnt2;
		rt=trie2[rt][nxt];
	}
	flag2[rt]++;
}
void getfail2()
{
	queue<int> q;
	for(int i=0;i<26;i++)
	{
		if(trie2[0][i])
		{
			fail2[trie2[0][i]]=0;
			q.push(trie2[0][i]);
		}
	}
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		//flag2[now]+=flag2[last2[now]];
		for(int i=0;i<26;i++)
		{
			if(trie2[now][i])
			{
				fail2[trie2[now][i]]=trie2[fail2[now]][i];
				last2[trie2[now][i]]=flag2[fail2[trie2[now][i]]]?fail2[trie2[now][i]]:last2[fail2[trie2[now][i]]];
				q.push(trie2[now][i]);
			}
			else
				trie2[now][i]=trie2[fail2[now]][i];
		}
	}
}
void query2(char ss[])
{
	int now=0,ans=0;
	int len=strlen(ss);
	for(int i=0;i<len;i++)
	{
		now=trie2[now][ss[i]-'a'];
		int id=flag2[now]?now:last2[now];
		while(id)
		{
			st[i]+=flag2[id];
			id=last2[id];
		}
		//st[i]+=flag2[now];
	}
}
int main()
{
	scanf("%s",s);
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",t);
		int len=strlen(t);
		insert(t,len);
		for(int i=0;i<len;i++)
		{
			re[i]=t[len-i-1];
		}
		insert2(re,len);
	}
	getfail();
	query(s);
	getfail2();
	int len=strlen(s);
	for(int i=0;i<len;i++)
	{
		rr[i]=s[len-i-1];
	}
	query2(rr);
	ll ans=0;
	for(int i=0;i<len;i++)
	{
		ans=ans+1ll*ed[i]*st[len-i-2];
	}
	printf("%I64d\n",ans);
	return 0;
}


#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int maxm=1e6+10;
int trie1[maxm][27],cntword1[maxm],flag1[maxm],fail1[maxm],last1[maxm],ed[maxm],st[maxm];
int trie2[maxm][27],cntword2[maxm],flag2[maxm],fail2[maxm],last2[maxm];
int cnt1,cnt2;
char s[maxm],t[maxm],re[maxm],rr[maxm];
void insert(char ss[],int len)
{
	int rt=0;
	//int len=strlen(ss+1);
	for(int i=0;i<len;i++)
	{
		int nxt=ss[i]-'a';
		if(!trie1[rt][nxt])
			trie1[rt][nxt]=++cnt1;
		rt=trie1[rt][nxt];
	}
	flag1[rt]++;
}
void getfail()
{
	queue<int> q;
	for(int i=0;i<26;i++)
	{
		if(trie1[0][i])
		{
			fail1[trie1[0][i]]=0;
			q.push(trie1[0][i]);
		}
	}
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		flag1[now]+=flag1[fail1[now]];
		for(int i=0;i<26;i++)
		{
			if(trie1[now][i])
			{
				fail1[trie1[now][i]]=trie1[fail1[now]][i];
				//last1[trie1[now][i]]=flag1[fail1[trie1[now][i]]]?fail1[trie1[now][i]]:last1[fail1[trie1[now][i]]];
				q.push(trie1[now][i]);
			}
			else
				trie1[now][i]=trie1[fail1[now]][i];
		}
	}
}
/*#define id now
#define last1 fail1
#define last2 fail2*/
void query(char ss[])
{
	int now=0,ans=0;
	int len=strlen(ss+1);
	for(int i=0;i<len;i++)
	{
		now=trie1[now][ss[i]-'a'];
		//int id=flag1[now]?now:last1[now];
		/*while(id)
		{
			ed[i]+=flag1[id];
			id=last1[id];
		}*/
		ed[i]+=flag1[now];
	}
}
void insert2(char ss[],int len)
{
	int rt=0;
	//int len=strlen(ss+1);
	for(int i=0;i<len;i++)
	{
		int nxt=ss[i]-'a';
		if(!trie2[rt][nxt])
			trie2[rt][nxt]=++cnt2;
		rt=trie2[rt][nxt];
	}
	flag2[rt]++;
}
void getfail2()
{
	queue<int> q;
	for(int i=0;i<26;i++)
	{
		if(trie2[0][i])
		{
			fail2[trie2[0][i]]=0;
			q.push(trie2[0][i]);
		}
	}
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		flag2[now]+=flag2[fail2[now]];
		for(int i=0;i<26;i++)
		{
			if(trie2[now][i])
			{
				fail2[trie2[now][i]]=trie2[fail2[now]][i];
				last2[trie2[now][i]]=flag2[fail2[trie2[now][i]]]?fail2[trie2[now][i]]:last2[fail2[trie2[now][i]]];
				q.push(trie2[now][i]);
			}
			else
				trie2[now][i]=trie2[fail2[now]][i];
		}
	}
}
void query2(char ss[])
{
	int now=0,ans=0;
	int len=strlen(ss);
	for(int i=0;i<len;i++)
	{
		now=trie2[now][ss[i]-'a'];
		//int id=flag2[now]?now:last2[now];
		/*while(id)
		{
			st[i]+=flag2[id];
			id=last2[id];
		}*/
		st[i]+=flag2[now];
	}
}
int main()
{
	scanf("%s",s);
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",t);
		int len=strlen(t);
		insert(t,len);
		for(int i=0;i<len;i++)
		{
			re[i]=t[len-i-1];
		}
		insert2(re,len);
	}
	getfail();
	query(s);
	getfail2();
	int len=strlen(s);
	for(int i=0;i<len;i++)
	{
		rr[i]=s[len-i-1];
	}
	query2(rr);
	ll ans=0;
	for(int i=0;i<len;i++)
	{
		ans=ans+1ll*ed[i]*st[len-i-2];
	}
	printf("%I64d\n",ans);
	return 0;
}


#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int maxm=2e5+10;
int trie1[maxm][27],cntword1[maxm],flag1[maxm],fail1[maxm],last1[maxm],ed[maxm],st[maxm];
int trie2[maxm][27],cntword2[maxm],flag2[maxm],fail2[maxm],last2[maxm];
int cnt1,cnt2;
char s[maxm],t[maxm],re[maxm],rr[maxm];
void insert(char ss[])
{
	int rt=0;
	int len=strlen(ss+1);
	for(int i=1;i<=len;i++)
	{
		int nxt=ss[i]-'a';
		if(!trie1[rt][nxt])
			trie1[rt][nxt]=++cnt1;
		rt=trie1[rt][nxt];
	}
	flag1[rt]++;
}
void getfail()
{
	queue<int> q;
	for(int i=0;i<26;i++)
	{
		if(trie1[0][i])
		{
			fail1[trie1[0][i]]=0;
			q.push(trie1[0][i]);
		}
	}
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		//flag1[now]+=flag1[last1[now]];
		for(int i=0;i<26;i++)
		{
			if(trie1[now][i])
			{
				fail1[trie1[now][i]]=trie1[fail1[now]][i];
				last1[trie1[now][i]]=flag1[fail1[trie1[now][i]]]?fail1[trie1[now][i]]:last1[fail1[trie1[now][i]]];
				q.push(trie1[now][i]);
			}
			else
				trie1[now][i]=trie1[fail1[now]][i];
		}
	}
}
void query(char ss[])
{
	int now=0,ans=0;
	int len=strlen(ss+1);
	for(int i=1;i<=len;i++)
	{
		now=trie1[now][ss[i]-'a'];
		int id=flag1[now]?now:last1[now];
		while(id)
		{
			ed[i]+=flag1[id];
			id=last1[id];
		}
		//ed[i]+=flag1[now];
	}
}
void insert2(char ss[])
{
	int rt=0;
	int len=strlen(ss+1);
	for(int i=1;i<=len;i++)
	{
		int nxt=ss[i]-'a';
		if(!trie2[rt][nxt])
			trie2[rt][nxt]=++cnt2;
		rt=trie2[rt][nxt];
	}
	flag2[rt]++;
}
void getfail2()
{
	queue<int> q;
	for(int i=0;i<26;i++)
	{
		if(trie2[0][i])
		{
			fail2[trie2[0][i]]=0;
			q.push(trie2[0][i]);
		}
	}
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		//flag2[now]+=flag2[last2[now]];
		for(int i=0;i<26;i++)
		{
			if(trie2[now][i])
			{
				fail2[trie2[now][i]]=trie2[fail2[now]][i];
				last2[trie2[now][i]]=flag2[fail2[trie2[now][i]]]?fail2[trie2[now][i]]:last2[fail2[trie2[now][i]]];
				q.push(trie2[now][i]);
			}
			else
				trie2[now][i]=trie2[fail2[now]][i];
		}
	}
}
void query2(char ss[])
{
	int now=0,ans=0;
	int len=strlen(ss+1);
	for(int i=1;i<=len;i++)
	{
		now=trie2[now][ss[i]-'a'];
		int id=flag2[now]?now:last2[now];
		while(id)
		{
			st[i]+=flag2[id];
			id=last2[id];
		}
		//st[i]+=flag2[now];
	}
}
int main()
{
	scanf("%s",s+1);
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",t+1);
		int len=strlen(t+1);
		insert(t);
		for(int i=1;i<=len;i++)
		{
			re[i]=t[len-i+1];
		}
		re[len+1]=re[len+2]='\0';
		insert2(re);
	}
	getfail();
	query(s);
	getfail2();
	int len=strlen(s+1);
	for(int i=1;i<=len;i++)
	{
		rr[i]=s[len-i+1];
	}
	query2(rr);
	ll ans=0;
	for(int i=1;i<=len;i++)
	{
		ans=ans+1ll*ed[i]*st[len-i];
	}
	printf("%I64d\n",ans);
	return 0;
}


#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int maxm=2e5+10;
int trie1[maxm][27],cntword1[maxm],flag1[maxm],fail1[maxm],last1[maxm],ed[maxm],st[maxm];
int trie2[maxm][27],cntword2[maxm],flag2[maxm],fail2[maxm],last2[maxm];
int cnt1,cnt2;
char s[maxm],t[maxm],re[maxm],rr[maxm];
void insert(char ss[])
{
	int rt=0;
	int len=strlen(ss+1);
	for(int i=1;i<=len;i++)
	{
		int nxt=ss[i]-'a';
		if(!trie1[rt][nxt])
			trie1[rt][nxt]=++cnt1;
		rt=trie1[rt][nxt];
	}
	flag1[rt]++;
}
void getfail()
{
	queue<int> q;
	for(int i=0;i<26;i++)
	{
		if(trie1[0][i])
		{
			fail1[trie1[0][i]]=0;
			q.push(trie1[0][i]);
		}
	}
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		//flag1[now]+=flag1[last1[now]];
		for(int i=0;i<26;i++)
		{
			if(trie1[now][i])
			{
				fail1[trie1[now][i]]=trie1[fail1[now]][i];
				last1[trie1[now][i]]=flag1[fail1[trie1[now][i]]]?fail1[trie1[now][i]]:last1[fail1[trie1[now][i]]];
				q.push(trie1[now][i]);
			}
			else
				trie1[now][i]=trie1[fail1[now]][i];
		}
	}
}
void query(char ss[])
{
	int now=0,ans=0;
	int len=strlen(ss+1);
	for(int i=1;i<=len;i++)
	{
		now=trie1[now][ss[i]-'a'];
		int id=flag1[now]?now:last1[now];
		while(id)
		{
			ed[i]+=flag1[id];
			id=last1[id];
		}
		//ed[i]+=flag1[now];
	}
}
void insert2(char ss[])
{
	int rt=0;
	int len=strlen(ss+1);
	for(int i=1;i<=len;i++)
	{
		int nxt=ss[i]-'a';
		if(!trie2[rt][nxt])
			trie2[rt][nxt]=++cnt2;
		rt=trie2[rt][nxt];
	}
	flag2[rt]++;
}
void getfail2()
{
	queue<int> q;
	for(int i=0;i<26;i++)
	{
		if(trie2[0][i])
		{
			fail2[trie2[0][i]]=0;
			q.push(trie2[0][i]);
		}
	}
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		//flag2[now]+=flag2[last2[now]];
		for(int i=0;i<26;i++)
		{
			if(trie2[now][i])
			{
				fail2[trie2[now][i]]=trie2[fail2[now]][i];
				last2[trie2[now][i]]=flag2[fail2[trie2[now][i]]]?fail2[trie2[now][i]]:last2[fail2[trie2[now][i]]];
				q.push(trie2[now][i]);
			}
			else
				trie2[now][i]=trie2[fail2[now]][i];
		}
	}
}
void query2(char ss[])
{
	int now=0,ans=0;
	int len=strlen(ss+1);
	for(int i=1;i<=len;i++)
	{
		now=trie2[now][ss[i]-'a'];
		int id=flag2[now]?now:last2[now];
		while(id)
		{
			st[i]+=flag2[id];
			id=last2[id];
		}
		//st[i]+=flag2[now];
	}
}
int main()
{
	scanf("%s",s+1);
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",t+1);
		int len=strlen(t+1);
		insert(t);
		for(int i=1;i<=len;i++)
		{
			re[i]=t[len-i+1];
		}
		insert2(re);
	}
	getfail();
	query(s);
	getfail2();
	int len=strlen(s+1);
	for(int i=1;i<=len;i++)
	{
		rr[i]=s[len-i+1];
	}
	query2(rr);
	ll ans=0;
	for(int i=1;i<=len;i++)
	{
		ans=ans+1ll*ed[i]*st[len-i];
	}
	printf("%I64d\n",ans);
	return 0;
}


#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int maxm=2e5+10;
int trie1[maxm][27],cntword1[maxm],flag1[maxm],fail1[maxm],last1[maxm],ed[maxm],st[maxm];
int trie2[maxm][27],cntword2[maxm],flag2[maxm],fail2[maxm],last2[maxm];
int cnt1,cnt2;
char s[maxm],t[maxm],re[maxm],rr[maxm];
void insert(char ss[],int len)
{
	int rt=0;
	//int len=strlen(ss+1);
	for(int i=0;i<len;i++)
	{
		int nxt=ss[i]-'a';
		if(!trie1[rt][nxt])
			trie1[rt][nxt]=++cnt1;
		rt=trie1[rt][nxt];
	}
	flag1[rt]++;
}
void getfail()
{
	queue<int> q;
	for(int i=0;i<26;i++)
	{
		if(trie1[0][i])
		{
			fail1[trie1[0][i]]=0;
			q.push(trie1[0][i]);
		}
	}
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		flag1[now]+=flag1[fail1[now]];
		for(int i=0;i<26;i++)
		{
			if(trie1[now][i])
			{
				fail1[trie1[now][i]]=trie1[fail1[now]][i];
				//last1[trie1[now][i]]=flag1[fail1[trie1[now][i]]]?fail1[trie1[now][i]]:last1[fail1[trie1[now][i]]];
				q.push(trie1[now][i]);
			}
			else
				trie1[now][i]=trie1[fail1[now]][i];
		}
	}
}
/*#define id now
#define last1 fail1
#define last2 fail2*/
void query(char ss[])
{
	int now=0,ans=0;
	int len=strlen(ss+1);
	for(int i=0;i<len;i++)
	{
		now=trie1[now][ss[i]-'a'];
		//int id=flag1[now]?now:last1[now];
		/*while(id)
		{
			ed[i]+=flag1[id];
			id=last1[id];
		}*/
		ed[i]+=flag1[now];
	}
}
void insert2(char ss[],int len)
{
	int rt=0;
	//int len=strlen(ss+1);
	for(int i=0;i<len;i++)
	{
		int nxt=ss[i]-'a';
		if(!trie2[rt][nxt])
			trie2[rt][nxt]=++cnt2;
		rt=trie2[rt][nxt];
	}
	flag2[rt]++;
}
void getfail2()
{
	queue<int> q;
	for(int i=0;i<26;i++)
	{
		if(trie2[0][i])
		{
			fail2[trie2[0][i]]=0;
			q.push(trie2[0][i]);
		}
	}
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		flag2[now]+=flag2[fail2[now]];
		for(int i=0;i<26;i++)
		{
			if(trie2[now][i])
			{
				fail2[trie2[now][i]]=trie2[fail2[now]][i];
				last2[trie2[now][i]]=flag2[fail2[trie2[now][i]]]?fail2[trie2[now][i]]:last2[fail2[trie2[now][i]]];
				q.push(trie2[now][i]);
			}
			else
				trie2[now][i]=trie2[fail2[now]][i];
		}
	}
}
void query2(char ss[])
{
	int now=0,ans=0;
	int len=strlen(ss);
	for(int i=0;i<len;i++)
	{
		now=trie2[now][ss[i]-'a'];
		//int id=flag2[now]?now:last2[now];
		/*while(id)
		{
			st[i]+=flag2[id];
			id=last2[id];
		}*/
		st[i]+=flag2[now];
	}
}
int main()
{
	scanf("%s",s);
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",t);
		int len=strlen(t);
		insert(t,len);
		for(int i=0;i<len;i++)
		{
			re[i]=t[len-i-1];
		}
		insert2(re,len);
	}
	getfail();
	query(s);
	getfail2();
	int len=strlen(s);
	for(int i=0;i<len;i++)
	{
		rr[i]=s[len-i-1];
	}
	query2(rr);
	ll ans=0;
	for(int i=0;i<len;i++)
	{
		ans=ans+1ll*ed[i]*st[len-i-2];
	}
	printf("%I64d\n",ans);
	return 0;
}


#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int maxm=2e5+10;
int trie1[maxm][27],cntword1[maxm],flag1[maxm],fail1[maxm],last1[maxm],ed[maxm],st[maxm];
int trie2[maxm][27],cntword2[maxm],flag2[maxm],fail2[maxm],last2[maxm];
int cnt1,cnt2;
char s[maxm],t[maxm],re[maxm],rr[maxm];
void insert(char ss[])
{
	int rt=0;
	int len=strlen(ss+1);
	for(int i=1;i<=len;i++)
	{
		int nxt=ss[i]-'a';
		if(!trie1[rt][nxt])
			trie1[rt][nxt]=++cnt1;
		rt=trie1[rt][nxt];
	}
	flag1[rt]++;
}
void getfail()
{
	queue<int> q;
	for(int i=0;i<26;i++)
	{
		if(trie1[0][i])
		{
			fail1[trie1[0][i]]=0;
			q.push(trie1[0][i]);
		}
	}
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		//flag1[now]+=flag1[last1[now]];
		for(int i=0;i<26;i++)
		{
			if(trie1[now][i])
			{
				fail1[trie1[now][i]]=trie1[fail1[now]][i];
				last1[trie1[now][i]]=flag1[fail1[trie1[now][i]]]?fail1[trie1[now][i]]:last1[fail1[trie1[now][i]]];
				q.push(trie1[now][i]);
			}
			else
				trie1[now][i]=trie1[fail1[now]][i];
		}
	}
}
void query(char ss[])
{
	int now=0,ans=0;
	int len=strlen(ss+1);
	for(int i=1;i<=len;i++)
	{
		now=trie1[now][ss[i]-'a'];
		int id=flag1[now]?now:fail1[now];
		while(id)
		{
			ed[i]+=flag1[id];
			id=fail1[id];
		}
		//ed[i]+=flag1[now];
	}
}
void insert2(char ss[])
{
	int rt=0;
	int len=strlen(ss+1);
	for(int i=1;i<=len;i++)
	{
		int nxt=ss[i]-'a';
		if(!trie2[rt][nxt])
			trie2[rt][nxt]=++cnt2;
		rt=trie2[rt][nxt];
	}
	flag2[rt]++;
}
void getfail2()
{
	queue<int> q;
	for(int i=0;i<26;i++)
	{
		if(trie2[0][i])
		{
			fail2[trie2[0][i]]=0;
			q.push(trie2[0][i]);
		}
	}
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		//flag2[now]+=flag2[last2[now]];
		for(int i=0;i<26;i++)
		{
			if(trie2[now][i])
			{
				fail2[trie2[now][i]]=trie2[fail2[now]][i];
				last2[trie2[now][i]]=flag2[fail2[trie2[now][i]]]?fail2[trie2[now][i]]:last2[fail2[trie2[now][i]]];
				q.push(trie2[now][i]);
			}
			else
				trie2[now][i]=trie2[fail2[now]][i];
		}
	}
}
void query2(char ss[])
{
	int now=0,ans=0;
	int len=strlen(ss+1);
	for(int i=1;i<=len;i++)
	{
		now=trie2[now][ss[i]-'a'];
		int id=flag2[now]?now:fail2[now];
		while(id)
		{
			st[i]+=flag2[id];
			id=fail2[id];
		}
		//st[i]+=flag2[now];
	}
}
int main()
{
	scanf("%s",s+1);
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",t+1);
		int len=strlen(t+1);
		insert(t);
		for(int i=1;i<=len;i++)
		{
			re[i]=t[len-i+1];
		}
		re[len+1]=re[len+2]='\0';
		insert2(re);
	}
	getfail();
	query(s);
	getfail2();
	int len=strlen(s+1);
	for(int i=1;i<=len;i++)
	{
		rr[i]=s[len-i+1];
	}
	query2(rr);
	ll ans=0;
	for(int i=1;i<=len;i++)
	{
		ans=ans+1ll*ed[i]*st[len-i];
	}
	printf("%I64d\n",ans);
	return 0;
}


#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int maxm=1e6+10;
int trie1[maxm][27],cntword1[maxm],flag1[maxm],fail1[maxm],last1[maxm],ed[maxm],st[maxm];
int trie2[maxm][27],cntword2[maxm],flag2[maxm],fail2[maxm],last2[maxm];
int cnt1,cnt2;
char s[maxm],t[maxm],re[maxm],rr[maxm];
void insert(char ss[])
{
	int rt=0;
	int len=strlen(ss+1);
	for(int i=1;i<=len;i++)
	{
		int nxt=ss[i]-'a';
		if(!trie1[rt][nxt])
			trie1[rt][nxt]=++cnt1;
		rt=trie1[rt][nxt];
	}
	flag1[rt]++;
}
void getfail()
{
	queue<int> q;
	for(int i=0;i<26;i++)
	{
		if(trie1[0][i])
		{
			fail1[trie1[0][i]]=0;
			q.push(trie1[0][i]);
		}
	}
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		for(int i=0;i<26;i++)
		{
			if(trie1[now][i])
			{
				fail1[trie1[now][i]]=trie1[fail1[now]][i];
				last1[trie1[now][i]]=flag1[fail1[trie1[now][i]]]?fail1[trie1[now][i]]:last1[fail1[trie1[now][i]]];
				q.push(trie1[now][i]);
			}
			else
				trie1[now][i]=trie1[fail1[now]][i];
		}
	}
}
void query(char ss[])
{
	int now=0,ans=0;
	int len=strlen(ss+1);
	for(int i=1;i<=len;i++)
	{
		now=trie1[now][ss[i]-'a'];
		int id=flag1[now]?now:last1[now];
		while(id)
		{
			ed[i]+=flag1[id];
			id=last1[id];
		}
	}
}
void insert2(char ss[])
{
	int rt=0;
	int len=strlen(ss+1);
	for(int i=1;i<=len;i++)
	{
		int nxt=ss[i]-'a';
		if(!trie2[rt][nxt])
			trie2[rt][nxt]=++cnt2;
		rt=trie2[rt][nxt];
	}
	flag2[rt]++;
}
void getfail2()
{
	queue<int> q;
	for(int i=0;i<26;i++)
	{
		if(trie2[0][i])
		{
			fail2[trie2[0][i]]=0;
			q.push(trie2[0][i]);
		}
	}
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		for(int i=0;i<26;i++)
		{
			if(trie2[now][i])
			{
				fail2[trie2[now][i]]=trie2[fail2[now]][i];
				last2[trie2[now][i]]=flag2[fail2[trie2[now][i]]]?fail2[trie2[now][i]]:last2[fail2[trie2[now][i]]];
				q.push(trie2[now][i]);
			}
			else
				trie2[now][i]=trie2[fail2[now]][i];
		}
	}
}
void query2(char ss[])
{
	int now=0,ans=0;
	int len=strlen(ss+1);
	for(int i=1;i<=len;i++)
	{
		now=trie2[now][ss[i]-'a'];
		int id=flag2[now]?now:last2[now];
		while(id)
		{
			st[i]+=flag2[id];
			id=last2[id];
		}
	}
}
int main()
{
	scanf("%s",s+1);
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",t+1);
		insert(t);
		int len=strlen(t+1);
		for(int i=1;i<=len;i++)
		{
			re[i]=t[len-i+1];
		}
		insert2(re);
	}
	getfail();
	query(s);
	getfail2();
	int len=strlen(s+1);
	for(int i=1;i<=len;i++)
	{
		rr[i]=s[len-i+1];
	}
	query2(rr);
	ll ans=0;
	for(int i=1;i<=len;i++)
	{
		ans=ans+1ll*ed[i]*st[len-i];
	}
	printf("%I64d\n",ans);
	return 0;
}


#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int maxm=2e5+10;
int trie1[maxm][27],cntword1[maxm],flag1[maxm],fail1[maxm],last1[maxm],ed[maxm],st[maxm];
int trie2[maxm][27],cntword2[maxm],flag2[maxm],fail2[maxm],last2[maxm];
int cnt1,cnt2;
char s[maxm],t[maxm],re[maxm],rr[maxm];
void insert(char ss[],int len)
{
	int rt=0;
	//int len=strlen(ss+1);
	for(int i=0;i<len;i++)
	{
		int nxt=ss[i]-'a';
		if(!trie1[rt][nxt])
			trie1[rt][nxt]=++cnt1;
		rt=trie1[rt][nxt];
	}
	flag1[rt]++;
}
void getfail()
{
	queue<int> q;
	for(int i=0;i<26;i++)
	{
		if(trie1[0][i])
		{
			fail1[trie1[0][i]]=0;
			q.push(trie1[0][i]);
		}
	}
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		//flag1[now]+=flag1[last1[now]];
		for(int i=0;i<26;i++)
		{
			if(trie1[now][i])
			{
				fail1[trie1[now][i]]=trie1[fail1[now]][i];
				last1[trie1[now][i]]=flag1[fail1[trie1[now][i]]]?fail1[trie1[now][i]]:last1[fail1[trie1[now][i]]];
				q.push(trie1[now][i]);
			}
			else
				trie1[now][i]=trie1[fail1[now]][i];
		}
	}
}
/*#define id now
#define last1 fail1
#define last2 fail2*/
void query(char ss[])
{
	int now=0,ans=0;
	int len=strlen(ss+1);
	for(int i=0;i<len;i++)
	{
		now=trie1[now][ss[i]-'a'];
		int id=flag1[now]?now:last1[now];
		while(id)
		{
			ed[i]+=flag1[id];
			id=last1[id];
		}
		//ed[i]+=flag1[now];
	}
}
void insert2(char ss[],int len)
{
	int rt=0;
	//int len=strlen(ss+1);
	for(int i=0;i<len;i++)
	{
		int nxt=ss[i]-'a';
		if(!trie2[rt][nxt])
			trie2[rt][nxt]=++cnt2;
		rt=trie2[rt][nxt];
	}
	flag2[rt]++;
}
void getfail2()
{
	queue<int> q;
	for(int i=0;i<26;i++)
	{
		if(trie2[0][i])
		{
			fail2[trie2[0][i]]=0;
			q.push(trie2[0][i]);
		}
	}
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		//flag2[now]+=flag2[last2[now]];
		for(int i=0;i<26;i++)
		{
			if(trie2[now][i])
			{
				fail2[trie2[now][i]]=trie2[fail2[now]][i];
				last2[trie2[now][i]]=flag2[fail2[trie2[now][i]]]?fail2[trie2[now][i]]:last2[fail2[trie2[now][i]]];
				q.push(trie2[now][i]);
			}
			else
				trie2[now][i]=trie2[fail2[now]][i];
		}
	}
}
void query2(char ss[])
{
	int now=0,ans=0;
	int len=strlen(ss);
	for(int i=0;i<len;i++)
	{
		now=trie2[now][ss[i]-'a'];
		int id=flag2[now]?now:last2[now];
		while(id)
		{
			st[i]+=flag2[id];
			id=last2[id];
		}
		//st[i]+=flag2[now];
	}
}
int main()
{
	scanf("%s",s);
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",t);
		int len=strlen(t);
		insert(t,len);
		for(int i=0;i<len;i++)
		{
			re[i]=t[len-i-1];
		}
		insert2(re,len);
	}
	getfail();
	query(s);
	getfail2();
	int len=strlen(s);
	for(int i=0;i<len;i++)
	{
		rr[i]=s[len-i-1];
	}
	query2(rr);
	ll ans=0;
	for(int i=0;i<len;i++)
	{
		ans=ans+1ll*ed[i]*st[len-i-2];
	}
	printf("%I64d\n",ans);
	return 0;
}


#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int maxm=2e5+10;
int trie1[maxm][27],cntword1[maxm],flag1[maxm],fail1[maxm],last1[maxm],ed[maxm],st[maxm];
int trie2[maxm][27],cntword2[maxm],flag2[maxm],fail2[maxm],last2[maxm];
int cnt1,cnt2;
char s[maxm],t[maxm],re[maxm],rr[maxm];
void insert(char ss[],int len)
{
	int rt=0;
	//int len=strlen(ss+1);
	for(int i=0;i<len;i++)
	{
		int nxt=ss[i]-'a';
		if(!trie1[rt][nxt])
			trie1[rt][nxt]=++cnt1;
		rt=trie1[rt][nxt];
	}
	flag1[rt]++;
}
void getfail()
{
	queue<int> q;
	for(int i=0;i<26;i++)
	{
		if(trie1[0][i])
		{
			fail1[trie1[0][i]]=0;
			q.push(trie1[0][i]);
		}
	}
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		flag1[now]+=flag1[last1[now]];
		for(int i=0;i<26;i++)
		{
			if(trie1[now][i])
			{
				fail1[trie1[now][i]]=trie1[fail1[now]][i];
				last1[trie1[now][i]]=flag1[fail1[trie1[now][i]]]?fail1[trie1[now][i]]:last1[fail1[trie1[now][i]]];
				q.push(trie1[now][i]);
			}
			else
				trie1[now][i]=trie1[fail1[now]][i];
		}
	}
}
/*#define id now
#define last1 fail1
#define last2 fail2*/
void query(char ss[])
{
	int now=0,ans=0;
	int len=strlen(ss+1);
	for(int i=0;i<len;i++)
	{
		now=trie1[now][ss[i]-'a'];
		//int id=flag1[now]?now:last1[now];
		/*while(id)
		{
			ed[i]+=flag1[id];
			id=last1[id];
		}*/
		ed[i]+=flag1[now];
	}
}
void insert2(char ss[],int len)
{
	int rt=0;
	//int len=strlen(ss+1);
	for(int i=0;i<len;i++)
	{
		int nxt=ss[i]-'a';
		if(!trie2[rt][nxt])
			trie2[rt][nxt]=++cnt2;
		rt=trie2[rt][nxt];
	}
	flag2[rt]++;
}
void getfail2()
{
	queue<int> q;
	for(int i=0;i<26;i++)
	{
		if(trie2[0][i])
		{
			fail2[trie2[0][i]]=0;
			q.push(trie2[0][i]);
		}
	}
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		flag2[now]+=flag2[last2[now]];
		for(int i=0;i<26;i++)
		{
			if(trie2[now][i])
			{
				fail2[trie2[now][i]]=trie2[fail2[now]][i];
				last2[trie2[now][i]]=flag2[fail2[trie2[now][i]]]?fail2[trie2[now][i]]:last2[fail2[trie2[now][i]]];
				q.push(trie2[now][i]);
			}
			else
				trie2[now][i]=trie2[fail2[now]][i];
		}
	}
}
void query2(char ss[])
{
	int now=0,ans=0;
	int len=strlen(ss);
	for(int i=0;i<len;i++)
	{
		now=trie2[now][ss[i]-'a'];
		//int id=flag2[now]?now:last2[now];
		/*while(id)
		{
			st[i]+=flag2[id];
			id=last2[id];
		}*/
		st[i]+=flag2[now];
	}
}
int main()
{
	scanf("%s",s);
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",t);
		int len=strlen(t);
		insert(t,len);
		for(int i=0;i<len;i++)
		{
			re[i]=t[len-i-1];
		}
		insert2(re,len);
	}
	getfail();
	query(s);
	getfail2();
	int len=strlen(s);
	for(int i=0;i<len;i++)
	{
		rr[i]=s[len-i-1];
	}
	query2(rr);
	ll ans=0;
	for(int i=0;i<len;i++)
	{
		ans=ans+1ll*ed[i]*st[len-i-2];
	}
	printf("%I64d\n",ans);
	return 0;
}


// OvO
#include <cstdio>
#include <cctype>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#ifdef ONLINE_JUDGE
#define freopen(a, b, c)
#endif

typedef long long int ll;

namespace IPT {

const int L = 1 << 21;
char buf[L], *front=buf, *end=buf;
char GetChar() {
  if (front == end) end = buf + fread(front = buf, 1, L, stdin);
  return (front == end) ? -1 : *(front++);
}
template <typename T>
inline void qr(T &x) {
  char ch = GetChar(), lst = 0; x = 0;
  while (!isdigit(ch)) lst = ch, ch = GetChar();
  while (isdigit(ch)) x = x * 10 + (ch ^ 48), ch = GetChar();
  if (lst == '-') x = -x;
}
template <typename T>
void qra(T *const __ary, int __n) {
  for (int i = 0; i < __n; ++i) qr(__ary[i]);
}
template <typename T>
int qrs(T *p) {
  T *beg = p;
  do *p = GetChar(); while (!isalnum(*p));
  do *(++p) = GetChar(); while (isalnum(*p));
  *p = 0;
  return p - beg;
}
template <typename T>
void qrdb(T &x) {
  char ch = GetChar(), lst = 0; x = 0;
  while (!isdigit(ch)) lst = ch, ch = GetChar();
  while (isdigit(ch)) { x = x * 10 + (ch - '0'); ch = GetChar(); }
  if (ch == '.') {
    ch = GetChar();
    for (double t = 0.1; isdigit(ch); t *= 0.1) {
      x += (t * (ch - '0'));
      ch = GetChar();
    }
  }
  if (lst == '-') x = -x;
}

} // namespace IPT

namespace OPT {

const int L = 30;
char buf[L];

template <typename T>
inline void qw(T x, const char aft = 0) {
  if (x < 0) { x = -x, putchar('-'); }
  int top = 0;
  do { buf[++top] = static_cast<char>(x % 10 + '0'); } while (x /= 10);
  while (top) putchar(buf[top--]);
  if (aft) putchar(aft);
}
template <typename T>
void qwa(T *const __ary, int __n, const char e1, const char e2) {
  int __dn = __n - 1;
  for (int i = 0; i < __dn; ++i) qw(__ary[i], e1);
  qw(__ary[__dn], e2);
}
template <typename T>
void qws(T *p, const int __n, const char ed) {
  for (int i = 0; i < __n; ++i) putchar(p[i]);
  if (ed) putchar(ed);
}
template <typename T>
void qws(T *p, const char ed) {
  while (*p) putchar(*p++);
  if(ed) putchar(ed);
}

} // namespace OPT

using IPT::qr;
using IPT::qra;
using IPT::qrs;
using IPT::qrdb;
using OPT::qw;
using OPT::qwa;
using OPT::qws;

namespace Fusu { void Main(); }

int main() {
  freopen("1.in", "r", stdin);
  Fusu::Main();
  return 0;
}

namespace Fusu {

const int maxt = 26;
const int maxn = 200005;

void Init();
void Calc();
void Build();

void Main() {
  Init();
  Build();
  Calc();
}

int n, m;
char s[maxn], t[maxn];

struct Node {
  int v;
  Node *fail;
  Node *son[maxt];
  std::vector<Node*> fson;

  Node() : v(0), fail(nullptr) {
    memset(son, 0, sizeof son);
  }

  void dfs() {
    for (auto u : fson) {
      u->v += v;
      u->dfs();
    }
  }
};
Node *r1, *r2;

void Ins(const int x, Node *u) {
  for (int i = 1, k = t[i] - 'a'; i <= x; k = t[++i] - 'a') {
    u = u->son[k] ? u->son[k] : (u->son[k] = new Node);
  }
  ++u->v;
}

void Init() {
  n = qrs(s + 1);
  qr(m);
  r1 = new Node; r2 = new Node();
  for (int i = 1, l; i <= m; ++i) {
    l = qrs(t + 1);
    Ins(l, r1);
    std::reverse(t + 1, t + 1 + l);
    Ins(l, r2);
  }
}

std::queue<Node*> Q;
void bfs(Node *r) {
  for (auto &v : r->son) if (v != nullptr) {
    Q.push(v); v->fail = r;
  } else {
    v = r;
  }
  for (Node *u, *v; !Q.empty(); Q.pop()) {
    u = Q.front();
    u->fail->fson.push_back(u);
    for (int i = 0; i < maxt; ++i) if ((v = u->son[i]) != nullptr) {
      v->fail = u->fail->son[i];
      Q.push(v);
    } else {
      u->son[i] = u->fail->son[i];
    }
  }
}

void Build() {
  bfs(r1);
  bfs(r2);
  r1->dfs();
  r2->dfs();
}

void calc(Node *u, int *ans) {
  for (int i = 1, x = s[i] - 'a'; i <= n; x = s[++i] - 'a') {
    u = u->son[x];
    ans[i] = u->v;
  }
}

int x[maxn], y[maxn];
void Calc() {
  calc(r1, x);
  std::reverse(s + 1, s + 1 + n);
  calc(r2, y);
  ll ans = 0;
  for (int i = 1; i < n; ++i) {
    ans += 1ll * x[i] * y[n - i];
  }
  qw(ans, '\n');
}

} // namespace Fusu


#include <cstdio>
#include <cctype>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#ifdef ONLINE_JUDGE
#define freopen(a, b, c)
#endif

typedef long long int ll;

namespace IPT {

const int L = 1 << 21;
char buf[L], *front=buf, *end=buf;
char GetChar() {
  if (front == end) end = buf + fread(front = buf, 1, L, stdin);
  return (front == end) ? -1 : *(front++);
}
template <typename T>
inline void qr(T &x) {
  char ch = GetChar(), lst = 0; x = 0;
  while (!isdigit(ch)) lst = ch, ch = GetChar();
  while (isdigit(ch)) x = x * 10 + (ch ^ 48), ch = GetChar();
  if (lst == '-') x = -x;
}
template <typename T>
void qra(T *const __ary, int __n) {
  for (int i = 0; i < __n; ++i) qr(__ary[i]);
}
template <typename T>
int qrs(T *p) {
  T *beg = p;
  do *p = GetChar(); while (!isalnum(*p));
  do *(++p) = GetChar(); while (isalnum(*p));
  *p = 0;
  return p - beg;
}
template <typename T>
void qrdb(T &x) {
  char ch = GetChar(), lst = 0; x = 0;
  while (!isdigit(ch)) lst = ch, ch = GetChar();
  while (isdigit(ch)) { x = x * 10 + (ch - '0'); ch = GetChar(); }
  if (ch == '.') {
    ch = GetChar();
    for (double t = 0.1; isdigit(ch); t *= 0.1) {
      x += (t * (ch - '0'));
      ch = GetChar();
    }
  }
  if (lst == '-') x = -x;
}

} // namespace IPT

namespace OPT {

const int L = 30;
char buf[L];

template <typename T>
inline void qw(T x, const char aft = 0) {
  if (x < 0) { x = -x, putchar('-'); }
  int top = 0;
  do { buf[++top] = static_cast<char>(x % 10 + '0'); } while (x /= 10);
  while (top) putchar(buf[top--]);
  if (aft) putchar(aft);
}
template <typename T>
void qwa(T *const __ary, int __n, const char e1, const char e2) {
  int __dn = __n - 1;
  for (int i = 0; i < __dn; ++i) qw(__ary[i], e1);
  qw(__ary[__dn], e2);
}
template <typename T>
void qws(T *p, const int __n, const char ed) {
  for (int i = 0; i < __n; ++i) putchar(p[i]);
  if (ed) putchar(ed);
}
template <typename T>
void qws(T *p, const char ed) {
  while (*p) putchar(*p++);
  if(ed) putchar(ed);
}

} // namespace OPT

using IPT::qr;
using IPT::qra;
using IPT::qrs;
using IPT::qrdb;
using OPT::qw;
using OPT::qwa;
using OPT::qws;

namespace Fusu { void Main(); }

int main() {
  freopen("1.in", "r", stdin);
  Fusu::Main();
  return 0;
}

namespace Fusu {

const int maxt = 26;
const int maxn = 200005;

void Init();
void Calc();
void Build();

void Main() {
  Init();
  Build();
  Calc();
}

int n, m;
char s[maxn], t[maxn];

struct Node {
  int v;
  Node *fail;
  Node *son[maxt];
  std::vector<Node*> fson;

  Node() : v(0), fail(nullptr) {
    memset(son, 0, sizeof son);
  }

  void dfs() {
    for (auto u : fson) {
      u->v += v;
      u->dfs();
    }
  }
};
Node *r1, *r2;

void Ins(const int x, Node *u) {
  for (int i = 1, k = t[i] - 'a'; i <= x; k = t[++i] - 'a') {
    u = u->son[k] ? u->son[k] : (u->son[k] = new Node);
  }
  ++u->v;
}

void Init() {
  n = qrs(s + 1);
  qr(m);
  r1 = new Node; r2 = new Node();
  for (int i = 1, l; i <= m; ++i) {
    l = qrs(t + 1);
    Ins(l, r1);
    std::reverse(t + 1, t + 1 + l);
    Ins(l, r2);
  }
}

std::queue<Node*> Q;
void bfs(Node *r) {
  for (auto &v : r->son) if (v != nullptr) {
    Q.push(v); v->fail = r;
  } else {
    v = r;
  }
  for (Node *u, *v; !Q.empty(); Q.pop()) {
    u = Q.front();
    u->fail->fson.push_back(u);
    for (int i = 0; i < maxt; ++i) if ((v = u->son[i]) != nullptr) {
      v->fail = u->fail->son[i];
      Q.push(v);
    } else {
      u->son[i] = u->fail->son[i];
    }
  }
}

void Build() {
  bfs(r1);
  bfs(r2);
  r1->dfs();
  r2->dfs();
}

void calc(Node *u, int *ans) {
  for (int i = 1, x = s[i] - 'a'; i <= n; x = s[++i] - 'a') {
    u = u->son[x];
    ans[i] = u->v;
  }
}

int x[maxn], y[maxn];
void Calc() {
  calc(r1, x);
  std::reverse(s + 1, s + 1 + n);
  calc(r2, y);
  ll ans = 0;
  for (int i = 1; i < n; ++i) {
    ans += 1ll * x[i] * y[n - i];
  }
  qw(ans, '\n');
}

} // namespace Fusu


#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long ll;
const int Maxn = 2e5;

struct Trie {
	struct TrieNode {
		TrieNode *son[27];
		int cnt;
	};
	TrieNode pool[Maxn + 5];
	TrieNode *root, *ncnt;
	TrieNode *newnode() {
		TrieNode *p = ++ncnt;
		for(int i = 0; i < 27; i++)
			p->son[i] = NULL;
		p->cnt = 0;
		return p;
	}
	void init() {
		ncnt = &pool[0];
		root = newnode();
	}
	void add(string str) {
		TrieNode *p = root;
		for(int i = 0; i < (int)str.length(); i++) {
			int ch = str[i] - 'a';
			if(!p->son[ch]) p->son[ch] = newnode();
			p = p->son[ch];
		}
		p->cnt++;
	}
	int count(string str, int pos) {
		int ret = 0;
		TrieNode *p = root;
		while(pos < (int)str.length()) {
			int ch = str[pos] - 'a';
			if(!p->son[ch]) break;
			p = p->son[ch];
			ret += p->cnt, pos++;
		}
		return ret;
	}
};

vector<int> Zfunction(string str) {
	vector<int> z(str.size(), 0);
	for(int i = 1, l = 0, r = 0; i < (int)str.length(); i++) {
		if(i <= r) z[i] = min(r - i + 1, z[i - l]);
		while(i + z[i] < (int)str.length() && str[i + z[i]] == str[z[i]])
			++z[i];
		if(i + z[i] - 1 > r)
			l = i, r = i + z[i] - 1;
	}
	return z;
}

int N, cnt[2][Maxn + 5];
string T, S[Maxn + 5];
const int LengthLimit = 500;
Trie tree;

int main() {
#ifdef LOACL
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	cin >> T >> N;
	for(int i = 1; i <= N; i++)
		cin >> S[i];
	for(int k = 0; k < 2; k++) {
		tree.init();
		for(int i = 1; i <= N; i++)
			if((int)S[i].length() > LengthLimit) {
				vector<int> z = Zfunction(S[i] + T);
				for(int j = 0; j < (int)T.length(); j++)
					cnt[k][j] += (z[(int)S[i].size() + j] >= (int)S[i].size());
			} else tree.add(S[i]);
		for(int i = 0; i < (int)T.length(); i++)
			cnt[k][i] += tree.count(T, i);
		for(int i = 1; i <= N; i++)
			reverse(S[i].begin(), S[i].end());
		reverse(T.begin(), T.end());
	}
	ll ans = 0;
	for(int i = 0; i <= (int)T.length(); i++)
		ans += 1LL * cnt[0][i] * cnt[1][T.length() - i];
	cout << ans << endl;
	return 0;
}


#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long ll;
const int Maxn = 2e5;

struct Trie {
	struct TrieNode {
		TrieNode *son[27];
		int cnt;
	};
	TrieNode pool[Maxn + 5];
	TrieNode *root, *ncnt;
	TrieNode *newnode() {
		TrieNode *p = ++ncnt;
		for(int i = 0; i < 27; i++)
			p->son[i] = NULL;
		p->cnt = 0;
		return p;
	}
	void init() {
		ncnt = &pool[0];
		root = newnode();
	}
	void add(string str) {
		TrieNode *p = root;
		for(int i = 0; i < (int)str.length(); i++) {
			int ch = str[i] - 'a';
			if(!p->son[ch]) p->son[ch] = newnode();
			p = p->son[ch];
		}
		p->cnt++;
	}
	int count(string str, int pos) {
		int ret = 0;
		TrieNode *p = root;
		while(pos < (int)str.length()) {
			int ch = str[pos] - 'a';
			if(!p->son[ch]) break;
			p = p->son[ch];
			ret += p->cnt, pos++;
		}
		return ret;
	}
};

vector<int> Zfunction(string str) {
	vector<int> z(str.size(), 0);
	for(int i = 1, l = 0, r = 0; i < (int)str.length(); i++) {
		if(i <= r) z[i] = min(r - i + 1, z[i - l]);
		while(i + z[i] < (int)str.length() && str[i + z[i]] == str[z[i]])
			++z[i];
		if(i + z[i] - 1 > r)
			l = i, r = i + z[i] - 1;
	}
	return z;
}

int N, cnt[2][Maxn + 5];
string T, S[Maxn + 5];
int LengthLimit;
Trie tree;

int main() {
#ifdef LOACL
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	cin >> T >> N;
	for(int i = 1; i <= N; i++)
		cin >> S[i], LengthLimit += (int)S[i].length();
	LengthLimit = (int)sqrt(LengthLimit);
	for(int k = 0; k < 2; k++) {
		tree.init();
		for(int i = 1; i <= N; i++)
			if((int)S[i].length() > LengthLimit) {
				vector<int> z = Zfunction(S[i] + T);
				for(int j = 0; j < (int)T.length(); j++)
					cnt[k][j] += (z[(int)S[i].size() + j] >= (int)S[i].size());
			} else tree.add(S[i]);
		for(int i = 0; i < (int)T.length(); i++)
			cnt[k][i] += tree.count(T, i);
		for(int i = 1; i <= N; i++)
			reverse(S[i].begin(), S[i].end());
		reverse(T.begin(), T.end());
	}
	ll ans = 0;
	for(int i = 0; i <= (int)T.length(); i++)
		ans += 1LL * cnt[0][i] * cnt[1][T.length() - i];
	cout << ans << endl;
	return 0;
}


#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long ll;
const int Maxn = 2e5;
const int LengthLimit = 500;

struct TrieNode {
	TrieNode *son[27];
	int cnt;
};
TrieNode pool[Maxn * 2 + 5];
TrieNode *root, *ncnt;
TrieNode *newnode() {
	TrieNode *p = ++ncnt;
	for(int i = 0; i < 27; i++)
		p->son[i] = NULL;
	p->cnt = 0;
	return p;
}
void init() {
	ncnt = &pool[0];
	root = newnode();
}
void add(const string &str) {
	TrieNode *p = root;
	for(int i = 0; i < (int)str.size(); i++) {
		int ch = str[i] - 'a';
		if(!p->son[ch]) p->son[ch] = newnode();
		p = p->son[ch];
	}
	p->cnt++;
}
int count(const string &str, int pos) {
	int ret = 0;
	TrieNode *p = root;
	while(pos < (int)str.size()) {
		int ch = str[pos] - 'a';
		if(!p->son[ch]) break;
		p = p->son[ch];
		ret += p->cnt, pos++;
	}
	return ret;
}

vector<int> Zfunction(string str) {
	vector<int> z(str.size(), 0);
	for(int i = 1, l = 0, r = 0; i < (int)str.size(); i++) {
		if(i < r) z[i] = min(r - i, z[i - l]);
		while(i + z[i] < (int)str.size() && str[i + z[i]] == str[z[i]])
			++z[i];
		if(i + z[i] > r)
			l = i, r = i + z[i];
	}
	return z;
}

int N;
string T, S[Maxn + 5];
vector<int> cnt[2];

int main() {
#ifdef LOACL
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> T;
	cin >> N;
	for(int i = 1; i <= N; i++)
		cin >> S[i];
	for(int k = 0; k < 2; k++) {
		init();
		cnt[k].assign((int)T.size() + 1, 0);
		for(int i = 1; i <= N; i++) {
			if((int)S[i].size() > LengthLimit) {
				vector<int> z = Zfunction(S[i] + T);
				for(int j = 0; j < (int)T.size(); j++)
					cnt[k][j] += (z[S[i].size() + j] >= (int)S[i].size());
			} else add(S[i]);
		}
		for(int i = 0; i < (int)T.size(); i++)
			cnt[k][i] += count(T, i);
		for(int i = 1; i <= N; i++)
			reverse(S[i].begin(), S[i].end());
		reverse(T.begin(), T.end());
	}
	ll ans = 0;
	for(int i = 0; i < (int)T.size() + 1; i++)
		ans += 1LL * cnt[0][i] * cnt[1][T.size() - i];
	cout << ans << endl;
	return 0;
}


#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long ll;
const int Maxn = 2e5;

struct Trie {
	struct TrieNode {
		TrieNode *son[27];
		int cnt;
	};
	TrieNode pool[Maxn + 5];
	TrieNode *root, *ncnt;
	TrieNode *newnode() {
		TrieNode *p = ++ncnt;
		for(int i = 0; i < 27; i++)
			p->son[i] = NULL;
		p->cnt = 0;
		return p;
	}
	void init() {
		ncnt = &pool[0];
		root = newnode();
	}
	void add(string str) {
		TrieNode *p = root;
		for(int i = 0; i < (int)str.length(); i++) {
			int ch = str[i] - 'a';
			if(!p->son[ch]) p->son[ch] = newnode();
			p = p->son[ch];
		}
		p->cnt++;
	}
	int count(string str, int pos) {
		int ret = 0;
		TrieNode *p = root;
		while(pos < (int)str.length()) {
			int ch = str[pos] - 'a';
			if(!p->son[ch]) break;
			p = p->son[ch];
			ret += p->cnt, pos++;
		}
		return ret;
	}
};

vector<int> Zfunction(string str) {
	vector<int> z(str.size(), 0);
	for(int i = 1, l = 0, r = 0; i < (int)str.length(); i++) {
		if(i < r) z[i] = min(r - i, z[i - l]);
		while(i + z[i] < (int)str.length() && str[i + z[i]] == str[z[i]])
			++z[i];
		if(i + z[i] > r)
			l = i, r = i + z[i];
	}
	return z;
}

int N, cnt[2][Maxn + 5];
string T, S[Maxn + 5];
const int LengthLimit = 500;
Trie tree;

int main() {
#ifdef LOACL
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> T >> N;
	for(int i = 1; i <= N; i++)
		cin >> S[i];
	for(int k = 0; k < 2; k++) {
		tree.init();
		for(int i = 1; i <= N; i++)
			if((int)S[i].length() > LengthLimit) {
				vector<int> z = Zfunction(S[i] + T);
				for(int j = 0; j < (int)T.length(); j++)
					cnt[k][j] += (z[(int)S[i].size() + j] >= (int)S[i].size());
			} else tree.add(S[i]);
		for(int i = 0; i < (int)T.length(); i++)
			cnt[k][i] += tree.count(T, i);
		for(int i = 1; i <= N; i++)
			reverse(S[i].begin(), S[i].end());
		reverse(T.begin(), T.end());
	}
	ll ans = 0;
	for(int i = 0; i <= (int)T.length(); i++)
		ans += 1LL * cnt[0][i] * cnt[1][T.length() - i];
	cout << ans << endl;
	return 0;
}


#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long ll;
const int Maxn = 5e5;

struct Trie {
	struct TrieNode {
		TrieNode *son[27];
		int cnt;
	};
	TrieNode pool[Maxn + 5];
	TrieNode *root, *ncnt;
	TrieNode *newnode() {
		TrieNode *p = ++ncnt;
		for(int i = 0; i < 27; i++)
			p->son[i] = NULL;
		p->cnt = 0;
		return p;
	}
	void init() {
		ncnt = &pool[0];
		root = newnode();
	}
	void add(string str) {
		TrieNode *p = root;
		for(int i = 0; i < (int)str.size(); i++) {
			int ch = str[i] - 'a';
			if(!p->son[ch]) p->son[ch] = newnode();
			p = p->son[ch];
		}
		p->cnt++;
	}
	int count(string str, int pos) {
		int ret = 0;
		TrieNode *p = root;
		while(pos < (int)str.size()) {
			int ch = str[pos] - 'a';
			if(!p->son[ch]) break;
			p = p->son[ch];
			ret += p->cnt, pos++;
		}
		return ret;
	}
};

vector<int> Zfunction(string str) {
	vector<int> z(str.size(), 0);
	for(int i = 1, l = 0, r = 0; i < (int)str.size(); i++) {
		if(i < r) z[i] = min(r - i, z[i - l]);
		while(i + z[i] < (int)str.size() && str[i + z[i]] == str[z[i]])
			++z[i];
		if(i + z[i] > r)
			l = i, r = i + z[i];
	}
	return z;
}

int N, cnt[2][Maxn + 5];
string T, S[Maxn + 5];
int LengthLimit;
Trie tree;

int main() {
#ifdef LOACL
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> T;
	cin >> N;
	for(int i = 1; i <= N; i++)
		cin >> S[i], LengthLimit += S[i].length();
	LengthLimit = sqrt(LengthLimit);
	for(int k = 0; k < 2; k++) {
		tree.init();
		for(int i = 1; i <= N; i++)
			if((int)S[i].size() > LengthLimit) {
				auto z = Zfunction(S[i] + T);
				for(int j = 0; j < (int)T.size(); j++)
					cnt[k][j] += (z[S[i].size() + j] >= (int)S[i].size());
			} else tree.add(S[i]);
		for(int i = 0; i < (int)T.size(); i++)
			cnt[k][i] += tree.count(T, i);
		for(int i = 1; i <= N; i++)
			reverse(S[i].begin(), S[i].end());
		reverse(T.begin(), T.end());
	}
	ll ans = 0;
	for(int i = 0; i <= (int)T.size(); i++)
		ans += 1LL * cnt[0][i] * cnt[1][T.size() - i];
	cout << ans << endl;
	return 0;
}


#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long ll;
const int Maxn = 5e5;

struct TrieNode {
	TrieNode *son[27];
	int cnt;
};
TrieNode pool[Maxn + 5];
TrieNode *root, *ncnt;
TrieNode *newnode() {
	TrieNode *p = ++ncnt;
	for(int i = 0; i < 27; i++)
		p->son[i] = NULL;
	p->cnt = 0;
	return p;
}
void init() {
	ncnt = &pool[0];
	root = newnode();
}
void add(string str) {
	TrieNode *p = root;
	for(int i = 0; i < (int)str.size(); i++) {
		int ch = str[i] - 'a';
		if(!p->son[ch]) p->son[ch] = newnode();
		p = p->son[ch];
	}
	p->cnt++;
}
int count(string str, int pos) {
	int ret = 0;
	TrieNode *p = root;
	while(pos < (int)str.size()) {
		int ch = str[pos] - 'a';
		if(!p->son[ch]) break;
		p = p->son[ch];
		ret += p->cnt, pos++;
	}
	return ret;
}

vector<int> Zfunction(string str) {
	vector<int> z(str.size(), 0);
	for(int i = 1, l = 0, r = 0; i < (int)str.size(); i++) {
		if(i < r) z[i] = min(r - i, z[i - l]);
		while(i + z[i] < (int)str.size() && str[i + z[i]] == str[z[i]])
			++z[i];
		if(i + z[i] > r)
			l = i, r = i + z[i];
	}
	return z;
}

int N, cnt[2][Maxn + 5];
string T, S[Maxn + 5];
int LengthLimit = 500;

int main() {
#ifdef LOACL
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> T;
	cin >> N;
	for(int i = 1; i <= N; i++)
		cin >> S[i];
	for(int k = 0; k < 2; k++) {
		init();
		for(int i = 1; i <= N; i++)
			if((int)S[i].size() > LengthLimit) {
				vector<int> z = Zfunction(S[i] + T);
				for(int j = 0; j < (int)T.size(); j++)
					cnt[k][j] += (z[S[i].size() + j] >= (int)S[i].size());
			} else add(S[i]);
		for(int i = 0; i < (int)T.size(); i++)
			cnt[k][i] += count(T, i);
		for(int i = 1; i <= N; i++)
			reverse(S[i].begin(), S[i].end());
		reverse(T.begin(), T.end());
	}
	ll ans = 0;
	for(int i = 0; i < (int)T.size() + 1; i++)
		ans += 1LL * cnt[0][i] * cnt[1][T.size() - i];
	cout << ans << endl;
	return 0;
}


#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long ll;
const int Maxn = 2e5;

struct TrieNode {
	TrieNode *son[27];
	int cnt;
};
TrieNode pool[Maxn * 2 + 5];
TrieNode *root, *ncnt;
TrieNode *newnode() {
	TrieNode *p = ++ncnt;
	for(int i = 0; i < 27; i++)
		p->son[i] = NULL;
	p->cnt = 0;
	return p;
}
void init() {
	ncnt = &pool[0];
	root = newnode();
}
void add(const string &str) {
	TrieNode *p = root;
	for(int i = 0; i < (int)str.size(); i++) {
		int ch = str[i] - 'a';
		if(!p->son[ch]) p->son[ch] = newnode();
		p = p->son[ch];
	}
	p->cnt++;
}
int count(const string &str, int pos) {
	int ret = 0;
	TrieNode *p = root;
	while(pos < (int)str.size()) {
		int ch = str[pos] - 'a';
		if(!p->son[ch]) break;
		p = p->son[ch];
		ret += p->cnt, pos++;
	}
	return ret;
}

vector<int> Zfunction(string str) {
	vector<int> z(str.size(), 0);
	for(int i = 1, l = 0, r = 0; i < (int)str.size(); i++) {
		if(i < r) z[i] = min(r - i, z[i - l]);
		while(i + z[i] < (int)str.size() && str[i + z[i]] == str[z[i]])
			++z[i];
		if(i + z[i] > r)
			l = i, r = i + z[i];
	}
	return z;
}

int N;
string T;
vector<string> S;
int LengthLimit = 500;
vector<int> cnt[2];

int main() {
#ifdef LOACL
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> T;
	cin >> N;
	S.resize(N);
	for(int i = 0; i < N; i++)
		cin >> S[i];
	for(int k = 0; k < 2; k++) {
		init();
		cnt[k].assign((int)T.size() + 1, 0);
		for(int i = 0; i < N; i++) {
			if((int)S[i].size() > LengthLimit) {
				vector<int> z = Zfunction(S[i] + T);
				for(int j = 0; j < (int)T.size(); j++)
					cnt[k][j] += (z[S[i].size() + j] >= (int)S[i].size());
			} else add(S[i]);
		}
		for(int i = 0; i < (int)T.size(); i++)
			cnt[k][i] += count(T, i);
		for(int i = 0; i < N; i++)
			reverse(S[i].begin(), S[i].end());
		reverse(T.begin(), T.end());
	}
	ll ans = 0;
	for(int i = 0; i < (int)T.size() + 1; i++)
		ans += 1LL * cnt[0][i] * cnt[1][T.size() - i];
	cout << ans << endl;
	return 0;
}


#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long ll;
const int Maxn = 2e5;

struct TrieNode {
	TrieNode *son[27];
	int cnt;
};
TrieNode pool[Maxn * 2 + 5];
TrieNode *root, *ncnt;
TrieNode *newnode() {
	TrieNode *p = ++ncnt;
	for(int i = 0; i < 27; i++)
		p->son[i] = NULL;
	p->cnt = 0;
	return p;
}
void init() {
	ncnt = &pool[0];
	root = newnode();
}
void add(string str) {
	TrieNode *p = root;
	for(int i = 0; i < (int)str.size(); i++) {
		int ch = str[i] - 'a';
		if(!p->son[ch]) p->son[ch] = newnode();
		p = p->son[ch];
	}
	p->cnt++;
}
int count(string str, int pos) {
	int ret = 0;
	TrieNode *p = root;
	while(pos < (int)str.size()) {
		int ch = str[pos] - 'a';
		if(!p->son[ch]) break;
		p = p->son[ch];
		ret += p->cnt, pos++;
	}
	return ret;
}

vector<int> Zfunction(string str) {
	vector<int> z(str.size(), 0);
	for(int i = 1, l = 0, r = 0; i < (int)str.size(); i++) {
		if(i < r) z[i] = min(r - i, z[i - l]);
		while(i + z[i] < (int)str.size() && str[i + z[i]] == str[z[i]])
			++z[i];
		if(i + z[i] > r)
			l = i, r = i + z[i];
	}
	return z;
}

int N;
string T;
string S[Maxn + 5];
int LengthLimit = 500;
vector<int> cnt[2];

int main() {
#ifdef LOACL
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> T;
	cin >> N;
	for(int i = 0; i < N; i++)
		cin >> S[i];
	for(int k = 0; k < 2; k++) {
		init();
		cnt[k].assign((int)T.size() + 1, 0);
		for(int i = 0; i < N; i++)
			if((int)S[i].size() > LengthLimit) {
				vector<int> z = Zfunction(S[i] + T);
				for(int j = 0; j < (int)T.size(); j++)
					cnt[k][j] += (z[S[i].size() + j] >= (int)S[i].size());
			} else add(S[i]);
		for(int i = 0; i < (int)T.size(); i++)
			cnt[k][i] += count(T, i);
		for(int i = 1; i <= N; i++)
			reverse(S[i].begin(), S[i].end());
		reverse(T.begin(), T.end());
	}
	ll ans = 0;
	for(int i = 0; i < (int)T.size() + 1; i++)
		ans += 1LL * cnt[0][i] * cnt[1][T.size() - i];
	cout << ans << endl;
	return 0;
}


#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long ll;
const int Maxn = 5e5;

struct Trie {
	struct TrieNode {
		TrieNode *son[27];
		int cnt;
	};
	TrieNode pool[Maxn + 5];
	TrieNode *root, *ncnt;
	TrieNode *newnode() {
		TrieNode *p = ++ncnt;
		for(int i = 0; i < 27; i++)
			p->son[i] = NULL;
		p->cnt = 0;
		return p;
	}
	void init() {
		ncnt = &pool[0];
		root = newnode();
	}
	void add(string str) {
		TrieNode *p = root;
		for(int i = 0; i < (int)str.length(); i++) {
			int ch = str[i] - 'a';
			if(!p->son[ch]) p->son[ch] = newnode();
			p = p->son[ch];
		}
		p->cnt++;
	}
	int count(string str, int pos) {
		int ret = 0;
		TrieNode *p = root;
		while(pos < (int)str.length()) {
			int ch = str[pos] - 'a';
			if(!p->son[ch]) break;
			p = p->son[ch];
			ret += p->cnt, pos++;
		}
		return ret;
	}
};

vector<int> Zfunction(string str) {
	vector<int> z(str.size(), 0);
	for(int i = 1, l = 0, r = 0; i < (int)str.length(); i++) {
		if(i < r) z[i] = min(r - i, z[i - l]);
		while(i + z[i] < (int)str.length() && str[i + z[i]] == str[z[i]])
			++z[i];
		if(i + z[i] > r)
			l = i, r = i + z[i];
	}
	return z;
}

int N, cnt[2][Maxn + 5];
string T, S[Maxn + 5];
const int LengthLimit = 500;
Trie tree;

int main() {
#ifdef LOACL
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> T >> N;
	for(int i = 1; i <= N; i++)
		cin >> S[i];
	for(int k = 0; k < 2; k++) {
		tree.init();
		for(int i = 1; i <= N; i++)
			if((int)S[i].length() > LengthLimit) {
				vector<int> z = Zfunction(S[i] + T);
				for(int j = 0; j < (int)T.length(); j++)
					cnt[k][j] += (z[(int)S[i].size() + j] >= (int)S[i].size());
			} else tree.add(S[i]);
		for(int i = 0; i < (int)T.length(); i++)
			cnt[k][i] += tree.count(T, i);
		for(int i = 1; i <= N; i++)
			reverse(S[i].begin(), S[i].end());
		reverse(T.begin(), T.end());
	}
	ll ans = 0;
	for(int i = 0; i <= (int)T.length(); i++)
		ans += 1LL * cnt[0][i] * cnt[1][T.length() - i];
	cout << ans << endl;
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int NN=2e5+4;
string s[NN];
int ne[NN][2],st[NN][30][2],sum[NN][2],res[NN][2],idx,len;
void insert(string x,int k)
{
	int len=x.size(),u=0;
	for(int i=0;i<len;i++)
	{
		if(!st[u][x[i]-'a'][k])
			st[u][x[i]-'a'][k]=++idx;
		u=st[u][x[i]-'a'][k];
	}
	sum[u][k]++;
}
void before_ACAM()
{
	queue<int>q;
	for(int k=0;k<2;k++)
	{
		for(int i=0;i<26;i++)
			if(st[0][i][k])
				q.push(st[0][i][k]);
		while(q.size())
		{
			int t=q.front();
			q.pop();
			for(int i=0;i<26;i++)
			{
				int u=st[t][i][k];
				if(u)
				{
					ne[u][k]=st[ne[t][k]][i][k];
					sum[u][k]+=sum[ne[u][k]][k];
					q.push(u);
				}
				else
					st[t][i][k]=st[ne[t][k]][i][k];
			}
		}
	}
}
void ACAM(string t,int k)
{
	int u=0;
	for(int i=0;i<len;i++)
	{
		u=st[u][t[i]-'a'][k];
		res[i][k]=sum[u][k];
	}
}
int main()
{
	string t;
	int n;
	cin>>t>>n;
	len=t.size();
	for(int i=1;i<=n;i++)
	{
		cin>>s[i];
		insert(s[i],0);
		reverse(s[i].begin(),s[i].end());
		insert(s[i],1);
	}
	before_ACAM();
	ACAM(t,0);
	reverse(t.begin(),t.end());
	ACAM(t,1);
	long long ans=0;
	for(int i=0;i<len-1;i++)
		ans+=1ll*res[i][0]*res[len-i-2][1];
	cout<<ans;
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int NN=2e5+4;
string s[NN];
int ne[NN][2],st[NN][30][2],sum[NN][2],res[NN][2],idx[2],len;
void insert(string x,int k)
{
	int len=x.size(),u=0;
	for(int i=0;i<len;i++)
	{
		if(!st[u][x[i]-'a'][k])
			st[u][x[i]-'a'][k]=++idx[k];
		u=st[u][x[i]-'a'][k];
	}
	sum[u][k]++;
}
void before_ACAM()
{
	queue<int>q;
	for(int k=0;k<2;k++)
	{
		for(int i=0;i<26;i++)
			if(st[0][i][k])
				q.push(st[0][i][k]);
		while(q.size())
		{
			int t=q.front();
			q.pop();
			for(int i=0;i<26;i++)
			{
				int u=st[t][i][k];
				if(u)
				{
					ne[u][k]=st[ne[t][k]][i][k];
					sum[u][k]+=sum[ne[u][k]][k];
					q.push(u);
				}
				else
					st[t][i][k]=st[ne[t][k]][i][k];
			}
		}
	}
}
void ACAM(string t,int k)
{
	int u=0;
	for(int i=0;i<len;i++)
	{
		u=st[u][t[i]-'a'][k];
		res[i][k]=sum[u][k];
	}
}
int main()
{
	string t;
	int n;
	cin>>t>>n;
	len=t.size();
	for(int i=1;i<=n;i++)
	{
		cin>>s[i];
		insert(s[i],0);
		reverse(s[i].begin(),s[i].end());
		insert(s[i],1);
	}
	before_ACAM();
	ACAM(t,0);
	reverse(t.begin(),t.end());
	ACAM(t,1);
	long long ans=0;
	for(int i=0;i<len-1;i++)
		ans+=1ll*res[i][0]*res[len-i-2][1];
	cout<<ans;
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+7;
using ll = long long;
string t;
int c[N], revc[N], nxt[N];
vector<string> ls;
struct Trie {
    int nxt[N][26], tot, rt, cnt[N], fail[N];
    void init() {
        tot = 0;
        rt = newnode();
    }
    int newnode() {
        ++tot;
        memset(nxt[tot], 0, sizeof(nxt[tot]));
        cnt[tot] = 0;
        return tot;
    }
    void insert(const string& s) {
        int now = rt;
        for(int i=0; i<s.length(); ++i) {
            int ch = s[i]-'a';
            if(nxt[now][ch]==0) nxt[now][ch]=newnode();
            now = nxt[now][ch];
        }
        ++cnt[now];
//        printf("now: %d, c: %d\n", now, cnt[now]);
    }
    void build()
    {
        queue<int> q;
        for(int i=0;i<26;++i)
        {
            if(nxt[rt][i]==0)
                nxt[rt][i]=rt;
            else
            {
                fail[nxt[rt][i]]=rt;
                q.push(nxt[rt][i]);
            }
        }
        while(!q.empty())
        {
            int now=q.front();q.pop();
            cnt[now] += cnt[fail[now]];
            for(int i=0;i<26;++i)
            {
                if(nxt[now][i]==0)
                    nxt[now][i]=nxt[fail[now]][i];
                else
                {
                    fail[nxt[now][i]]=nxt[fail[now]][i];
                    q.push(nxt[now][i]);
                }
            }
        }
    }
    void solve(int *c) {
        int now = rt;
        for(int i=0; i<t.length(); ++i) {
            int ch = t[i]-'a';
            now = nxt[now][ch];
            c[i] += cnt[now];
        }
    }
}trie;
void cal(int *c) {
//    puts("cal");
    trie.init();
    for(string &s : ls) trie.insert(s);
    trie.build();
//    for(int i=1; i<=trie.tot; i++) printf("cnt[%d]=%d\n", i, trie.cnt[i]);
    trie.solve(c);
//    for(int i=0; i<t.length(); ++i) {
//        printf("c[%d]=%d\n", i, c[i]);
//    }
}
int main() {
    ios::sync_with_stdio(false);
    cin >> t;
    int n;
    cin >> n;
    for(int i=0; i<n; ++i) {
        string s;
        cin >> s;
        ls.push_back(s);
    }
    cal(c);
    reverse(t.begin(), t.end());
    for(string &s : ls) reverse(s.begin(), s.end());
    cal(revc);
    ll ans = 0;
    for(int i=0; i+1<t.length(); ++i) {
        ans += 1LL*c[i]*revc[t.length()-i-2];
//        printf("%d %d\n", i, t.length()-i-2);
    }
    cout << ans<<endl;
}


#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+7;
const int B = 300;
using ll = long long;
string t;
int c[N], revc[N], nxt[N];
vector<string> ls, ss;
struct Trie {
    int nxt[N][26], tot, rt, cnt[N];
    void init() {
        tot = 0;
        rt = newnode();
    }
    int newnode() {
        ++tot;
        memset(nxt[tot], 0, sizeof(nxt[tot]));
        cnt[tot] = 0;
        return tot;
    }
    void insert(const string& s) {
        int now = rt;
        for(int i=0; i<s.length(); ++i) {
            int ch = s[i]-'a';
            if(nxt[now][ch]==0) nxt[now][ch]=newnode();
            now = nxt[now][ch];
        }
        ++cnt[now];
    }
    int query(const string& t, int start) {
        int res = 0;
        int now = rt;
        for(int i=start; i<t.length(); ++i) {
            int ch = t[i]-'a';
            now = nxt[now][ch];
            if(now==0) break;
            res += cnt[now];
        }
        return res;
    }
}trie;
void kmp_pre(const string &s) {
    int i,j;
    j=nxt[0]=-1;
    i=0;
    while(i<s.length()) {
        while(-1!=j&&s[i]!=s[j]) j=nxt[j];
        nxt[++i]=++j;
    }
}
void kmp(const string &s, int *c) {
    int i=0, j=0, ans=0;
    kmp_pre(s);
    while(i<t.length()) {
        while(-1!=j&&t[i]!=s[j]) j=nxt[j];
        ++i; ++j;
        if(j>=s.length()) {
            ++c[i-s.length()];
            j=nxt[j];
        }
    }
}
void cal(int *c) {
//    puts("cal");
    trie.init();
    for(string &s : ss) {
        trie.insert(s);
    }
    for(int i=0; i<t.length(); ++i) {
        c[i]=trie.query(t, i);
//        printf("c[%d]=%d\n", i, c[i]);
    }
    for(string &s : ls) {
        kmp(s, c);
    }
//    for(int i=0; i<t.length(); ++i) {
//        printf("c[%d]=%d\n", i, c[i]);
//    }
}
int main() {
    ios::sync_with_stdio(false);
    cin >> t;
    int n;
    cin >> n;
    for(int i=0; i<n; ++i) {
        string s;
        cin >> s;
        if(s.length()<B) ss.push_back(s);
        else ls.push_back(s);
    }
    cal(c);
    reverse(t.begin(), t.end());
    for(string &s : ls) reverse(s.begin(), s.end());
    for(string &s : ss) reverse(s.begin(), s.end());
    cal(revc);
    ll ans = 0;
    for(int i=1; i<t.length(); ++i) {
        ans += 1LL*c[i]*revc[t.length()-i];
//        printf("%d %d\n", i, t.length()-i);
    }
    cout << ans<<endl;
}


#include <bits/stdc++.h>
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// #include <ext/pb_ds/priority_queue.hpp>
//#pragma GCC optimize("O3")
//#pragma GCC target("sse4")
//#pragma GCC target("avx2")

#define deb(x) cout << #x << " = " << x << "\n"
#define all(x) (x).begin(), (x).end()
#define len(x) (int) x.size()
#define lsb(x) (x) & -(x)
#define l(x) (x << 1) + 1
#define r(x) (x << 1) + 2
#define v(x) (int)(x - 'a')

#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define lb lower_bound
#define ub upper_bound

using namespace std;
// using namespace __gnu_pbds;
typedef long long ll;
typedef long double ld;
typedef pair <int, int> pii;
typedef pair <ld, ld> pld;
typedef pair <ll, ll> pll;

// template <class T1, class T2, class T3 = less <T1>> using pb_map = tree <T1, T2, T3, rb_tree_tag, tree_order_statistics_node_update>;
//template <class T1, class T2 = less <T1>> using pb_heap = __gnu_pbds::priority_queue <T1, T2, binary_heap_tag>;
// template <class T1, class T2 = null_type, class T3 = hash <T1>> using pb_umap = gp_hash_table <T1, T2, T3>;
template <class T1, class T2, class T3 = hash <T1>> using umap = unordered_map <T1, T2, T3>;
template <class T> using uset = unordered_set <T>;
template <class T> using vec = vector <T>;

const ll infll = numeric_limits <ll>::max() >> 1;
const int inf = numeric_limits <int>::max() >> 1;
const int N = 2e5 + 1;
const int L = 26;
int n, q;
int cur;
ll ans;

int beg[N];
int fin[N];

struct Trie {
    int nxt[N][L];
    int gon[N][L];
    int link[N];
    int par[N];
    int chr[N];
    int cnt[N];
    int fin[N];
} trie;

string t;
string p[N];

int get_link(int);
int get_go(int, int);

void input() {
    cin >> t;
    cin >> q;
    n = len(t);
    for(int i = 0; i < q; ++i) {
        cin >> p[i];
    }
}

void insert(string &s) {
    int node = 0;
    for(char c: s) {
        int j = v(c);
        if(!trie.nxt[node][j]) {
            trie.nxt[node][j] = ++cur;
            trie.par[cur] = node;
            trie.chr[cur] = j;
        }
        node = trie.nxt[node][j];
    }
    trie.fin[node]++;
}

int get_link(int node) {
    if(trie.link[node] == -1) {
        if(!node || !trie.par[node]) {
            trie.link[node] = 0;
            trie.cnt[node] = trie.fin[node];
        }
        else {
            trie.link[node] = get_go(get_link(trie.par[node]), trie.chr[node]);
            get_link(trie.link[node]);
            trie.cnt[node] = trie.fin[node] + trie.cnt[trie.link[node]];
        }
    }
    return trie.link[node];
}

int get_go(int node, int c) {
    if(trie.gon[node][c] == -1) {
        if(trie.nxt[node][c]) {
            trie.gon[node][c] =
            trie.nxt[node][c];
        }
        else {
            trie.gon[node][c] = node? get_go(get_link(node), c): 0;
        }
    }
    return trie.gon[node][c];
}

void aho_corasick(int arr[]) {
    fill(trie.gon[0], trie.gon[N], -1);
    fill(trie.link, trie.link + N, -1);
    fill(trie.fin, trie.fin + N, 0);
    cur = 0;
    for(int i = 0; i < q; ++i) {
        insert(p[i]);
    }
    int node = 0;
    for(int i = 0; i < n; ++i) {
        node = get_go(node, v(t[i]));
        get_link(node);
        arr[i] = trie.cnt[node];
    }
}

void reverse_all() {
    reverse(all(t));
    for(int i = 0; i < q; ++i) {
        reverse(all(p[i]));
    }
}

void solve() {
    aho_corasick(beg);
    reverse_all();
    aho_corasick(fin);
    reverse(fin, fin + n);
    for(int i = 0; i < n - 1; ++i) {
        ans += 1ll * beg[i] * fin[i + 1];
    }
    cout << ans << "\n";
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    input();
    solve();
}