Problem: G： 検閲により置換 (Censored String)

Problem Statement

You are given the string S, and the set of strings \mathcal P whose size is N. Now we consider applying the following operation to S:

* Choose exactly one character in S, and replace it with '*'.



Let s_i be a i-th character of S, S_{ij} be a consecutive substring in S such that  S = s_i s_{i+1} $\cdots$  s_j, and p_k as the k-th string of P. Your task is to calculate the minimum number of operations for satisfying the following condition.

* For all pairs (S_{ij}, p_k), it is satisfied that S_{ij} \neq p_k.



Input

An input is given in the following format.


S
N
p_1
p_2
$\vdots$
p_N


* In line 1, you are given the string S.
* In line 2, given an integer N. N means the size of P.
* From line 3 to the end, given p_i, the i-th string of P.



Constraints

* 1 \leq |S| \leq 10^5
* 1 \leq N \leq 10^5
* 1 \leq |p_1| + |p_2| +  $\cdots$  + |p_N| \leq 10^5
* If i \neq j, it is guaranteed that p_i \neq p_j
* S, and p_i include lowercase letters only



Output

Print the minimum number of operations in one line.

Sample Input 1


brainfuck
1
fuck


Sample Output 1


1

For example, if you change "brainfuck" into "brainf*ck", you can satisfy the condition. You have to perform operation at least once, and it is the minimum value.

Sample Input 2


aaa
1
a


Sample Output 2


3

You have to operate for all characters.

Sample Input 3


hellshakeyano
3
hell
shake
key


Sample Output 3


2

In this case, for example, if you change "hellshakeyano" into "h*llsha*eyano", you can satisfy the condition. Notice if you replace one character, it might happen that several strings in the set P, which appear as the consecutive substring of S, simultaneously disappear.





Example

Input

brainfuck
1
fuck


Output

1

Solution (in CPP):

Solution:
// g++ -std=c++11 a.cpp
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>	
#include<map>
#include<set>
#include<utility>
#include<cmath>
#include<random>
#include<cstring>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<sstream>
#include<iomanip>
#include<assert.h>
#include<typeinfo>
#define loop(i,a,b) for(int i=a;i<b;i++) 
#define rep(i,a) loop(i,0,a)
#define pb push_back
#define all(in) in.begin(),in.end()
#define shosu(x) fixed<<setprecision(x)
using namespace std;
//kaewasuretyuui
typedef long long ll;
//#define int ll
typedef int Def;
typedef pair<Def,Def> pii;
typedef vector<Def> vi;
typedef vector<vi> vvi;
typedef vector<pii> vp;
typedef vector<vp> vvp;
typedef vector<string> vs;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef pair<Def,pii> pip;
typedef vector<pip>vip;
#define mt make_tuple
typedef tuple<int,int,int> tp;
typedef vector<tp> vt;
template<typename A,typename B>bool cmin(A &a,const B &b){return a>b?(a=b,true):false;}
template<typename A,typename B>bool cmax(A &a,const B &b){return a<b?(a=b,true):false;}
//template<class C>constexpr int size(const C &c){return (int)c.size();}
//template<class T,size_t N> constexpr int size(const T (&xs)[N])noexcept{return (int)N;}
const double PI=acos(-1);
const double EPS=1e-7;
Def inf = sizeof(Def) == sizeof(long long) ? 2e18 : 1e9+10;
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
#define MAX 26
#define OFFSET 'a'
struct Node{
	int nxt[MAX+1]; // 次のalphabeteのノード番号
	int exist; // 子ども以下に存在する文字列の数の合計
	vi accept; // その文字列id
	Node() : exist(0){memset(nxt, -1, sizeof(nxt));}
};
struct Trie{
	vector<Node>nodes;
	int root;
	Trie() : root(0){nodes.push_back(Node());}

	void update_direct(int node,int id){
		nodes[node].accept.push_back(id);
	}
	void update_child(int node,int child,int id){
		++nodes[node].exist;
	}
	void add(const string &str,int str_index,int node_index,int id){
		if(str_index == str.size()) 
			update_direct(node_index, id);
		else{
			const int c = str[str_index] - OFFSET;
			if(nodes[node_index].nxt[c] == -1) {
				nodes[node_index].nxt[c] = (int) nodes.size();
				nodes.push_back(Node());
			}
			add(str, str_index + 1, nodes[node_index].nxt[c], id);
			update_child(node_index, nodes[node_index].nxt[c], id);
		}
	}
	void add(const string &str,int id){add(str, 0, 0, id);}
	void add(const string &str){add(str, nodes[0].exist);}
	int size(){return (nodes[0].exist);}
	int nodesize(){return ((int) nodes.size());}
};
struct Aho_Corasick : Trie{
	static const int FAIL = MAX;
	vi correct;
	Aho_Corasick() : Trie() {}
	
	void build(){
		correct.resize(nodes.size());
		rep(i,nodes.size())correct[i]=(int)nodes[i].accept.size();

		queue<int> que;
		rep(i,MAX+1){
			if(~nodes[0].nxt[i]) {
				nodes[nodes[0].nxt[i]].nxt[FAIL] = 0;
				que.emplace(nodes[0].nxt[i]);
			}else nodes[0].nxt[i] = 0;
		}
		while(!que.empty()) {
			Node &now = nodes[que.front()];
			correct[que.front()] += correct[now.nxt[FAIL]];
			que.pop();
			rep(i,MAX){
				if(now.nxt[i] == -1) continue;
				int fail = now.nxt[FAIL];
				while(nodes[fail].nxt[i] == -1) {
					fail = nodes[fail].nxt[FAIL];
				}
				nodes[now.nxt[i]].nxt[FAIL] = nodes[fail].nxt[i];

				auto &u = nodes[now.nxt[i]].accept;
				auto &v = nodes[nodes[fail].nxt[i]].accept;
				vi accept;
				set_union(all(u),all(v),back_inserter(accept));
				u=accept;
				que.emplace(now.nxt[i]);
			}
		}
	}
	int match(const string &str,vi &result,int now=0){
		result.assign(size(),0);
		int count=0;
		for(auto &c:str) {
			while(nodes[now].nxt[c-OFFSET]==-1)now=nodes[now].nxt[FAIL];
			now = nodes[now].nxt[c-OFFSET];
			count += correct[now];
			for(auto &v:nodes[now].accept)result[v]++;
		}
		return count;
	}
	int next(int now,char c){
		while(nodes[now].nxt[c-OFFSET]==-1)now=nodes[now].nxt[FAIL];
		return nodes[now].nxt[c-OFFSET];
	}
};
int main(){
	string s;
	cin>>s;
	int n;
	cin>>n;
	vs p(n);
	rep(i,n)cin>>p[i];
	Aho_Corasick ac;
	rep(i,n)ac.add(p[i]);
	ac.build();
	int now=ac.root;
	vp dp;
	rep(i,s.size()){
		now=ac.next(now,s[i]);
		int ma=-1;
		for(int j:ac.nodes[now].accept){
			ma=max(ma,i+1-(int)p[j].size());
//			dp.pb({i+1,i+1-p[j].size()});
		}
		if(ma!=-1)dp.pb({i+1,ma});
//			if(dp[i+1-p[j].size()]>=0)(dp[i+1]+=dp[i+1-p[j].size()])%=1000000007;
	}
//	rep(i,dp.size())cout<<dp[i].first<<" "<<dp[i].second<<endl;
	sort(all(dp));
	int out=0;
	int last=-inf;
	rep(i,dp.size()){
		int a=dp[i].second,b=dp[i].first;
		if(last<a){
			last=b-1;
			out++;
		}
	}
	cout<<out<<endl;
}