设d(i)为从字符i开始的字符串的分解方案数,则d[i]= sum{(d[i]+len(x))}
x 为 d[i]代表的字符的前缀
/*
* @Author: CY__HHH
* @Date: 2020-09-04 00:56:59
* @LastEditTime: 2020-09-05 12:50:19
*/
#include<bits/stdc++.h> //树上DP Trie
#define rep(i, n) for(int i=0;i!=n;++i)
#define per(i, n) for(int i=n-1;i>=0;--i)
#define Rep(i, sta, n) for(int i=sta;i!=n;++i)
#define rep1(i, n) for(int i=1;i<=n;++i)
#define per1(i, n) for(int i=n;i>=1;--i)
#define Rep1(i, sta, n) for(int i=sta;i<=n;++i)
#define L rt<<1
#define R rt<<1|1
#define inf (0x3f3f3f3f)
#define llinf (1e18)
#define ALL(A) A.begin(),A.end()
#define SIZE(A) ((int)A.size())
#define MOD (20071027)
#define PII pair<int,int>
typedef long long i64;
using namespace std;
const int maxn = 2e6 + 32;
int Trie[maxn][26];
int total;
int dp[maxn];
bool vis[maxn];//judge是否为单词
void insert(string &str){
int root = 0;
for(auto &c:str){
int pos = c - 'a';
if(!Trie[root][pos])
Trie[root][pos] = ++total;
root = Trie[root][pos];
}
vis[root] = true;//当前节点为单词标记
}
void find(string str,int p){// p为当前位置
int root = 0;
for(int i=0;i!=(int)str.size();++i){
int pos = str[i] - 'a';
if(!Trie[root][pos])
return;//如果任何一个前缀都不存在
root = Trie[root][pos];
if(vis[root])//每一个单词前缀即为递推式
dp[p] = (dp[p] + dp[p + i + 1]) % MOD;
}
}
int main() {
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
string text; cin >> text;
int s; string temp;
cin >> s;
for(int i=0;i!=s;++i){
cin >> temp;
insert(temp);
}
int len = text.size();
dp[len] = 1;//dp界限
for(int i=len-1;i>=0;--i)
find(text.substr(i),i);
cout << dp[0] << endl;
return 0;
}