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

#define REP(i,n) for(int i=0;i<n;++i)

struct SuffixArray {
	struct SAComp {
		const int h; const vector<int> &g;
		SAComp(const int h_, const vector<int>&g_) : h(h_), g(g_) { ; }
		bool operator() (int a, int b) {
			return a == b ? false : g[a] != g[b] ? g[a] < g[b] : g[a + h] < g[b + h];
		}
	};

	static const int SIZE = 100000;
	int n;
	string str;
	vector<int> sa;
	vector<int> lcp;

	SuffixArray() { ; }
	SuffixArray(const string t) :str(t) {
		Init();
	}
	void Init() {
		n = str.size();
		buildSA();
		buildLCP();
	}

	// O(mlogn)

	////バグあるかも
	//int find(const string p) {
	//	int m = p.size();
	//	int left = 0;
	//	int right = n-m;
	//	while (left < right) {
	//		int mid = (left + right) / 2;
	//		if (str.substr(sa[mid],m)<p.substr(0,m)) { left = mid + 1; }
	//		else { right = mid; }
	//	}
	//	return str.substr(sa[left], m)== p.substr(0, m)? sa[left] : -1;
	//}
private:
	//O(nlog^2n)
	void buildSA() {
		sa = vector<int>(n + 1);
		vector<int>g(n + 1);
		vector<int>b(n + 1);
		REP(i, n + 1) { sa[i] = i; g[i] = str[i]; }
		b[0] = 0;
		b[n] = 0;
		SAComp f(0, g);
		sort(sa.begin(), sa.end(), SAComp(0, g));
		for (int h = 1; b[n] != n; h *= 2) {
			SAComp comp(h, g);
			sort(sa.begin(), sa.end(), comp);
			REP(i, n) b[i + 1] = b[i] + comp(sa[i], sa[i + 1]);
			REP(i, n + 1) g[sa[i]] = b[i];
		}
	}
	void buildLCP() {
		lcp = vector<int>(n + 1);
		int h = 0;
		vector<int>b(n + 1);
		REP(i, n + 1) { b[sa[i]] = i; }
		REP(i, n + 1) {
			if (b[i]) {
				for (int j = sa[b[i] - 1]; j + h < n && i + h < n && str[j + h] == str[i + h]; h++) { ; }
				lcp[b[i]] = h;
			}
			else {
				lcp[b[i]] = -1;
			}
			if (h > 0) { h--; }
		}
	}
public:
	//[l..r)がtestから始まる
	pair<int, int>getlr(string test) {
		pair<int, int>p;
		{
			int amin = 0;
			int amax = str.size() + 1;
			while (amin + 1 != amax) {
				int amid((amin + amax) / 2);
				string name = str.substr(sa[amid], test.size());
				if (name < test) {
					amin = amid;
				}
				else {
					amax = amid;
				}
			}
			p.first= amax;
		}
		{
			int amin = 0;
			int amax = str.size() + 1;
			while (amin + 1 != amax) {
				int amid((amin + amax + 1) / 2);
				string name = str.substr(sa[amid], test.size());
				if (name <= test) {
					amin = amid;
				}
				else {
					amax = amid;
				}
			}
			p.second = amax; 
		}
		return p;
	}

};

int N, M;
bool solve(const int now, const vector<vector<int>>&oks, bitset<12>&used,vector<string>&words,vector<int>&dp) {
	if (dp[used.to_ulong()])return false;
	dp[used.to_ulong()] = true;
	if (used.count() == N)return true;
	else {
		for (int i = 0; i < N; ++i) {
			if (!used[i] && oks[now][i]) {
				used[i] = true;
				if (solve(now + words[i].size(), oks, used, words,dp))return true;
				used[i] = false;
			}
		}
	}
	return false;
}
int main() { 
	while (true) { cin >> N >> M;
		if (N == 0 && M == 0)break;
		vector<string>words;
		for (int i = 0; i < N; ++i) {
			string st; cin >> st;
			words.push_back(st);
		}
		string str;
		for (int i = 0; i < M; ++i) {
			string st; cin >> st;
			str += st;
		}
		SuffixArray sa(str);

		vector<vector<int>>oks(str.size()+1, vector<int>(N));
		for (int i = 0; i < N; ++i) {
			string word(words[i]);
			int al, ar;
			auto p(sa.getlr(word));
			al = p.first;
			ar = p.second;
			for (int x = al; x < ar; ++x) {
				oks[sa.sa[x]][i] = true;
			}

		}

		int len_sum = 0;
		for (int i = 0; i < N; ++i)len_sum += words[i].size();
		int ans = 0;
		for (int i = 0; i <= int(str.size())-len_sum; ++i) {
			bitset<12>bs;
			vector<int>dp(1 << 12);
			if (solve(i, oks, bs, words,dp))ans++;
		}
		cout << ans << endl;
	}
	return 0;
}

Measured memory_bytes: 3392