Problem:
Problem G:
Search of Concatenated Strings
The amount of information on the World Wide Web is growing quite rapidly. In this information
explosion age, we must survive by accessing only the Web pages containing information relevant
to our own needs. One of the key technologies for this purpose is keyword search. By using
well-known search engines, we can easily access those pages containing useful information about
the topic we want to know.
There are many variations in keyword search problems. If a single string is searched in a given
text, the problem is quite easy. If the pattern to be searched consists of multiple strings, or
is given by some powerful notation such as regular expressions, the task requires elaborate
algorithms to accomplish efficiently.
In our problem, a number of strings (element strings) are given, but they are not directly
searched for. Concatenations of all the element strings in any order are the targets of the search
here.
For example, consider three element strings aa, b and ccc are given. In this case, the following
six concatenated strings are the targets of the search, i.e. they should be searched in the text.
aabccc
aacccb
baaccc
bcccaa
cccaab
cccbaa
The text may contain several occurrences of these strings. You are requested to count the
number of occurrences of these strings, or speaking more precisely, the number of positions of
occurrences in the text.
Two or more concatenated strings may be identical. In such cases, it is necessary to consider
subtle aspects of the above problem statement. For example, if two element strings are x and
xx, the string xxx is an occurrence of both the concatenation of x and xx and that of xx and x.
Since the number of positions of occurrences should be counted, this case is counted as one, not
two.
Two occurrences may overlap. For example, the string xxxx has occurrences of the concatenation
xxx in two different positions. This case is counted as two.
Input
The input consists of a number of datasets, each giving a set of element strings and a text. The
format of a dataset is as follows.
n m
e
1
e
2
.
.
.
e
n
t
1
t
2
.
.
.
t
m
The first line contains two integers separated by a space.
n
is the number of element strings.
m
is the number of lines used to represent the text.
n
is between 1 and 12, inclusive.
Each of the following n lines gives an element string. The length (number of characters) of an
element string is between 1 and 20, inclusive.
The last
m
lines as a whole give the text. Since it is not desirable to have a very long line, the
text is separated into m lines by newlines, but these newlines should be ignored. They are not
parts of the text. The length of each of these lines (not including the newline) is between 1 and
100, inclusive. The length of the text is between 1 and 5000, inclusive.
The element strings and the text do not contain characters other than lowercase letters.
The end of the input is indicated by a line containing two zeros separated by a space.
CAUTIO
...(truncated)

Submitted solutions:

code_snippet: #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=12;
int i,j,n,m;
char s[6000],ss[6000];
char c[20][50];
bool f[5500][1<<N];
int len,ll,l[N+3];
bool b[5030][N+1];

void check(int i,int j)
{
  for (int k=0;k<l[j];++k)
    {
      if (i>len) return;
      if (s[i++]!=c[j][k]) return;
    }
  b[i-1][j]=1;
}
  
int main()
{
  scanf("%d%d",&n,&m);
  while (n>0 || m>0)
    {
      for (i=1;i<=n;++i)
	{
	  scanf("%s",c[i]);
	  l[i]=strlen(c[i]);
	}
      len=0;
      for (j=1;j<=m;++j)
	{
	  scanf("%s",ss);
	  ll=strlen(ss);
	  for (i=0;i<ll;++i) s[++len]=ss[i];
	}
      memset(f,0,sizeof(f));
      memset(b,0,sizeof(b));
      for (i=1;i<=len;++i)
	for (j=1;j<=n;++j) check(i,j);  
      int maxn=1<<n;
      for (i=0;i<=len;++i) f[i][0]=1;
      for (i=1;i<=len;++i)
	for (j=1;j<=n;++j)
	  if (b[i][j])
	    for (int k=1;k<maxn;++k)
	      if (!f[i][k])
		if ((k|(1<<(j-1)))==k) f[i][k]|=f[i-l[j]][k^(1<<(j-1))];
      int ans=0;
      for (i=1;i<=len;++i)
	if (f[i][maxn-1]) ++ans;
      printf("%d\n",ans);
      scanf("%d%d",&n,&m);
    }
  return 0;
}
accuracy: 1
time_ms: 1030
memory_kb: 25336
final_rank: 4

code_snippet: #include <cstdio>
#include <cstring>
const int Maxn=12, Maxl=5003;
bool g[Maxl][Maxn];
char a[Maxn][23],s[103],str[Maxl];
int f[Maxl][1<<Maxn];

int main()
{
	int T=0, n,m,len,i,j,k,l,ans;
	scanf("%d%d",&n,&m);
	while (n)
	{
		for (i=0; i<n; ++i) scanf("%s",a[i]);
		len=0;
		while (m--)
		{
			scanf("%s",s);
			l=strlen(s);
			for (i=0; i<l; ++i) str[len++]=s[i];
		}
		str[len]='\0';
		for (i=0; i<len; ++i)
			for (j=0; j<n; ++j)
			{
				g[i][j]=true;
				l=strlen(a[j]);
				for (k=0; k<l; ++k)
					if (str[i+k]!=a[j][k])
					{
						g[i][j]=false; break;
					}
			}
		++T;
		for (i=0; i<len; ++i)
		{
			f[i][0]=T;
			for (j=0; j<(1<<n); ++j)
				if (f[i][j]==T)
					for (k=0; k<n; ++k)
						if ((j&(1<<k))==0 && g[i][k]) f[i+strlen(a[k])][j|(1<<k)]=T;
		}
		ans=0;
		for (i=0; i<=len; ++i)
			if (f[i][(1<<n)-1]==T) ++ans;
		printf("%d\n",ans);
		scanf("%d%d",&n,&m);
	}
	return 0;
}
accuracy: 1
time_ms: 3390
memory_kb: 83008
final_rank: 18

code_snippet: #line 2 "cp-library/src/cp-template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull  = unsigned long long;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
template < class T, class U > T ceil (T x, U y) { return (x > 0 ? (x + y - 1) / y :           x / y); }
template < class T, class U > T floor(T x, U y) { return (x > 0 ?           x / y : (x - y + 1) / y); }
int popcnt(i32 x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(i64 x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }

#line 2 "cp-library/src/utility/rep_itr.hpp"
template < class T > struct itr_rep {
    T i, d;
    constexpr itr_rep(const T i) noexcept : i(i), d(1) {}
    constexpr itr_rep(const T i, const T d) noexcept : i(i), d(d) {}
    void operator++() noexcept { i += d; }
    constexpr int operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr_rep x) const noexcept { return d > 0 ? i < x.i : i > x.i; }
};

template < class T > struct rep {
    const itr_rep< T > s, t;
    constexpr rep(const T t) noexcept : s(0), t(t) {}
    constexpr rep(const T s, const T t) noexcept : s(s), t(t) {}
    constexpr rep(const T s, const T t, const T d) noexcept : s(s, d), t(t, d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};

template < class T > struct revrep {
    const itr_rep < T > s, t;
    constexpr revrep(const T t) noexcept : s(t - 1, -1), t(-1, -1) {}
    constexpr revrep(const T s, const T t) noexcept : s(t - 1, -1), t(s - 1, -1) {}
    constexpr revrep(const T s, const T t, const T d) noexcept : s(t - 1, -d), t(s - 1, -d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};
#line 3 "cp-library/src/utility/io.hpp"

/* 128bit integer */
istream& operator>>(istream& is, i128& x) {
    std::string s; is >> s;
    int pm = (s[0] == '-');
    x = 0;
    for(int i : rep(pm, int(s.size()))) x = x * 10 + (s[i] - '0');
    if(pm) x *= -1;
    return is;
}
ostream& operator<<(ostream& os, const i128& x) {
    if(x == 0) return os << '0';
    i128 y = x;
    if(y < 0) { os << '-'; y *= -1; }
    std::vector<int> ny;
    while(y > 0) { ny.push_back(y % 10); y /= 10; }
    for(int i : revrep(ny.size())) os << ny[i];
    return os;
}

template < class S, class T > istream& operator>>(istream& is,       std::pair< S, T >& x) { is >> x.first        >> x.second; return is; }
template < class S, class T > ostream& operator<<(ostream& os, const std::pair< S, T >& x) { os << x.first << " " << x.second; return os; }

namespace scanner {
    struct sca {
        template < class T > operator T() {
            T s; std::cin >> s; return s;
        }
    };
    struct vec {
        int n;
        vec(int n) : n(n) {}
        template < class T > operator std::vector< T >() {
            std::vector< T > v(n);
            for(T& x : v) std::cin >> x;
            return v;
        }
    };
    struct mat {
        int h, w;
        mat(int h, int w) : h(h), w(w) {}
        template < class T > operator std::vector< std::vector< T > >() {
            std::vector m(h, std::vector< T >(w));
            for(std::vector< T >& v : m) for(T& x : v) std::cin >> x;
            return m;
        }
    };
    struct speedup {
        speedup() {
            std::cin.tie(0);
            std::ios::sync_with_stdio(0);
        }
    } speedup_instance;
}
scanner::sca in() { return scanner::sca(); }
scanner::vec in(int n) { return scanner::vec(n); }
scanner::mat in(int h, int w) { return scanner::mat(h, w); }

namespace printer {
    void precision(int d) { std::cout << std::fixed << std::setprecision(d); }
    void flush() { std::cout.flush(); }
}

template < class T >
ostream& operator<<(ostream& os, const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) { os << a[i]; if(i != n - 1) os << ' '; }
    return os;
}

int print() { std::cout << '\n'; return 0; }
template < class head, class... tail > int print(head&& h, tail&&... t) {
    std::cout << h; if(sizeof...(tail)) std::cout << ' ';
    return print(std::forward<tail>(t)...);
}
template < class T > int print_n(const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) std::cout << a[i] << "\n";
    return 0;
}


#line 2 "cp-library/src/utility/key_val.hpp"

template < class K, class V >
struct key_val {
    K key; V val;
    key_val() {}
    key_val(K key, V val) : key(key), val(val) {}
    template < std::size_t Index >
    std::tuple_element_t< Index, key_val >& get() {
        if constexpr (Index == 0) return key;
        if constexpr (Index == 1) return val;
    }
};

namespace std {

template < class K, class V > struct tuple_size < key_val< K, V > > : integral_constant< size_t, 2 > {};
template < class K, class V > struct tuple_element < 0, key_val< K, V > > { using type = K; };
template < class K, class V > struct tuple_element < 1, key_val< K, V > > { using type = V; };

}
#line 2 "cp-library/src/utility/vec_op.hpp"
template < class T > key_val< int, T > max_of(const vector< T >& a) {
    int i = std::max_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class T > key_val< int, T > min_of(const vector< T >& a) {
    int i = std::min_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class S, class T > S sum_of(const vector< T >& a) {
    S sum = 0;
    for(const T x : a) sum += x;
    return sum;
}
template < class S, class T > vector< S > freq_of(const vector< T >& a, T L, T R) {
    vector< S > res(R - L, S(0));
    for(const T x : a) res[x - L] += 1;
    return res;
}
template < class S, class T > struct prefix_sum {
    vector< S > s;
    prefix_sum(const vector< T >& a) : s(a) {
        s.insert(s.begin(), S(0));
        for(int i : rep(a.size())) s[i + 1] += s[i];
    }
    // [L, R)
    S sum(int L, int R) { return s[R] - s[L]; }
};
#line 3 "cp-library/src/utility/heap.hpp"

template < class T > using heap_min = std::priority_queue< T, std::vector< T >, std::greater< T > >;
template < class T > using heap_max = std::priority_queue< T, std::vector< T >, std::less< T > >;

#line 27 "cp-library/src/cp-template.hpp"

#line 1 "cp-library/src/algorithm/bin_search.hpp"
template < class T, class F >
T bin_search(T ok, T ng, F f) {
    while(abs(ng - ok) > 1) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template < class T, class F >
T bin_search_real(T ok, T ng, F f, int step = 80) {
    while(step--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
#line 2 "cp-library/src/algorithm/argsort.hpp"

template < class T > std::vector< int > argsort(const std::vector< T > &a) {
    std::vector< int > ids((int)a.size());
    std::iota(ids.begin(), ids.end(), 0);
    std::sort(ids.begin(), ids.end(), [&](int i, int j) {
        return a[i] < a[j] || (a[i] == a[j] && i < j);
    });
    return ids;
}
#line 1 "macro.hpp"
namespace macro {

using size_type = int;
template < class container > void  sort(container& a) { std::sort(std:: begin(a), std:: end(a)); }
template < class container > void rsort(container& a) { std::sort(std::rbegin(a), std::rend(a)); }
template < class container > void reverse(container& a) { std::reverse(std::begin(a), std::end(a)); }
template < class container > void unique(container& a) {
    std::sort(std::begin(a), std::end(a));
    a.erase(std::unique(std::begin(a), std::end(a)), std::end(a));
}
template < class container > container  sorted(const container& a) { container b = a;  sort(b); return std::move(b); }
template < class container > container rsorted(const container& a) { container b = a; rsort(b); return std::move(b); }
template < class container, class compare > void sort(container& a, const compare& cmp) { std::sort(std::begin(a), std::end(a), cmp); }
template < class container, class compare > container sorted(const container& a, const compare& cmp) { container b = a; sort(b, cmp); return std::move(b); }
template < class container, class value > size_type lower_bound(const container& a, const value& x) { return std::lower_bound(std::begin(a), std::end(a), x) - std::begin(a); }
template < class container, class value > size_type upper_bound(const container& a, const value& x) { return std::upper_bound(std::begin(a), std::end(a), x) - std::begin(a); }

const std::vector<std::pair<size_type, size_type>> dir4 = { {+1,  0}, {-1,  0}, { 0, +1}, { 0, -1} };
const std::vector<std::pair<size_type, size_type>> dir8 = { {-1, -1}, {-1,  0}, {-1, +1}, { 0, -1}, { 0, +1}, {+1, -1}, {+1,  0}, {+1, +1} };

#ifdef _DEBUG
#define debug(x) std::cout << "[" << __LINE__ << "] " << #x << ": " << x << std::endl
#else
#define debug(x)
#endif

template < class container > void concat(container& a, const container& b) {
    a.insert(std::end(a), std::begin(b), std::end(b));
}
std::vector<size_type> iota(const size_type n) {
    std::vector<size_type> I(n);
    std::iota(std::begin(I), std::end(I), 0);
    return I;
}
template < class container > std::vector<size_type> sort_idx(const container& a) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return a[i] < a[j] or (a[i] == a[j] and i < j); });
    return I;
}
template < class container, class compare > std::vector<size_type> sort_idx(const container& a, const compare& cmp) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return cmp(a[i], a[j]) or (a[i] == a[j] and i < j); });
    return std::move(I);
}

struct grid {
    using size_type = int;
    size_type H, W;
    grid(const size_type H, const size_type W) : H(H), W(W) {}
    bool contains(const size_type i, const size_type j) {
        return 0 <= i and i < H and 0 <= j and j < W;
    }
};

using f64 = long double;

template < class T > vector< T >& operator++(vector< T >& a) { for(T& x : a) x++; return a; }
template < class T > vector< T >& operator--(vector< T >& a) { for(T& x : a) x--; return a; }
template < class T > vector< T >  operator++(vector< T >& a, signed) { vector< T > res = a; for(T& x : a) x++; return res; }
template < class T > vector< T >  operator--(vector< T >& a, signed) { vector< T > res = a; for(T& x : a) x--; return res; }

} // namespace macro

using namespace macro;
#line 3 "cp-library/src/utility/random.hpp"

namespace randnum {

static uint seed;
static std::mt19937 mt;
struct gen_seed {
    gen_seed() {
        seed = std::random_device()();
        mt = std::mt19937(seed);
    }
} gs;

// [L, R)
template < class T >
T gen_int(T L, T R) {
    return std::uniform_int_distribution< T >(L, R - 1)(mt);
}

template < class T >
T get_real(T L, T R) {
    return std::uniform_real_distribution< T >(L, R)(mt);
}

}
#line 3 "cp-library/src/utility/hash.hpp"

template < int num_of_mod = 2 >
struct hash_vector : public array<ll, num_of_mod> {
    //static constexpr ll MODS[] = {999999937, 1000000007, 1000000009, 1000000021};
    static constexpr ll MODS[] = {1000000021, 999999937, 1000000007, 1000000009, };
    static_assert(1 <= num_of_mod and num_of_mod <= 4);
    using array<ll, num_of_mod>::operator[];
    using H = hash_vector;
    static constexpr int n = num_of_mod;
    hash_vector() : array<ll,n>() {}
    hash_vector(ll x) : H() { for(int i : rep(n)) (*this)[i] = x % MODS[i]; }
    H& operator+=(const H& rhs) { for(int i : rep(n)) if(((*this)[i] += rhs[i]) >= MODS[i]) (*this)[i] -= MODS[i]; return *this; }
    H& operator-=(const H& rhs) { for(int i : rep(n)) if(((*this)[i] += MODS[i] - rhs[i]) >= MODS[i]) (*this)[i] -= MODS[i]; return *this; }
    H& operator*=(const H& rhs) { for(int i : rep(n)) (*this)[i] = (*this)[i] * rhs[i] % MODS[i]; return *this; }
    H& operator+=(const ll rhs) { for(int i : rep(n)) if(((*this)[i] += rhs % MODS[i]) >= MODS[i]) (*this)[i] -= MODS[i]; return *this; }
    H& operator-=(const ll rhs) { for(int i : rep(n)) if(((*this)[i] += MODS[i] - rhs % MODS[i]) >= MODS[i]) (*this)[i] -= MODS[i]; return *this; }
    H& operator*=(const ll rhs) { for(int i : rep(n)) (*this)[i] = (*this)[i] * (rhs % MODS[i]) % MODS[i]; return *this; }
    H operator+(const H& rhs) const { return H(*this) += rhs; }
    H operator-(const H& rhs) const { return H(*this) -= rhs; }
    H operator*(const H& rhs) const { return H(*this) *= rhs; }
    H operator+(const ll rhs) const { return H(*this) += rhs; }
    H operator-(const ll rhs) const { return H(*this) -= rhs; }
    H operator*(const ll rhs) const { return H(*this) *= rhs; }
    H operator-() const { return H().fill(0) - *this; }
    friend H operator+(ll x, const H& y) { return H(x) + y; }
    friend H operator-(ll x, const H& y) { return H(x) + y; }
    friend H operator*(ll x, const H& y) { return H(x) * y; }
    bool operator==(const H& rhs) { for(int i : rep(n)) if((*this)[i] != rhs[i]) return false; return true ; }
    bool operator!=(const H& rhs) { for(int i : rep(n)) if((*this)[i] != rhs[i]) return true ; return false; }
};
#line 4 "cp-library/src/string/rolling_hash.hpp"


constexpr ll BASE = 10007;
template< int num_of_mod = 2 >
struct rolling_hash {

    static const ll BASE;

    vector< hash_vector< num_of_mod > > pb, hs;
    rolling_hash() {}
    rolling_hash(const string& s) {
        int n = s.size();
        hs.resize(n + 1); hs[0].fill(0);
        pb.resize(n + 1); pb[0].fill(1);
        for(int i : rep(n)) {
            hs[i + 1] = hs[i] * BASE + s[i];
            pb[i + 1] = pb[i] * BASE;
        }
    }

    // [l, r)
    hash_vector< num_of_mod > get(int l, int r) const {
        return hs[r] - hs[l] * pb[r - l];
    }

    hash_vector< num_of_mod > concat(hash_vector< num_of_mod > h1, hash_vector< num_of_mod > h2, int h2_len) {
        assert(0 <= h2_len and h2_len < int(pb.size()));
        return h1 * pb[h2_len] + h2;
    }

    template < int n >
    static int lcp(const rolling_hash< n >& rh1, int l1, int r1, const rolling_hash< n >& rh2, int l2, int r2) {
        int lo = -1, hi = min(r1 - l1, r2 - l2) + 1;
        while(hi - lo > 1) {
            int mid = (lo + hi) / 2;
            (rh1.get(l1, l1 + mid) == rh2.get(l2, l2 + mid) ? lo : hi) = mid;
        }
        return lo;
    }

    template < int n >
    static int cmp(const string& s1, const rolling_hash< n >& rh1, int l1, int r1,
                   const string& s2, const rolling_hash< n >& rh2, int l2, int r2) {
        int len = lcp(rh1, l1, r1, rh2, l2, r2);
        if(len == r1 - l1 && len == r2 - l2) return 0;
        if(len == r1 - l1) return -1;
        if(len == r2 - l2) return +1;
        return (s1[l1 + len] < s2[l2 + len] ? -1 : +1);
    }
};

template < int num_of_mod >
const ll rolling_hash< num_of_mod >::BASE = randnum::gen_int<ll>(ll(0), hash_vector< num_of_mod >::MODS[0]);
#line 4 "A.cpp"
using RH = rolling_hash< 2 >;

int dp[5050][1 << 12];

int solve(int n, int m) {
    vector<string> e = in(n);
    vector<RH> he(n);
    for(int i : rep(n)) he[i] = RH(e[i]);

    int ans = 0;
    string t = "";
    for(int _ : rep(m)) { string s = in(); t += s; }
    const int sz_t = t.size();
    RH ht(t);
    for(int i : rep(sz_t + 1)) for(int S : rep(1 << n)) dp[i][S] = 0;
    for(int i : rep(sz_t + 1)) dp[i][0] = 1;
    for(int i : rep(sz_t + 1)) {
        for(int S : rep(1 << n)) if(dp[i][S]) {
            for(int k : rep(n)) {
                if((S >> k & 1) == 0) {
                    const int sz_e = e[k].size();
                    if(i + sz_e <= sz_t and ht.get(i, i + sz_e) == he[k].get(0, sz_e)) {
                        dp[i + sz_e][S | (1 << k)] = 1;
                    }
                }
            }
        }
    }
    for(int i : rep(sz_t + 1)) ans += dp[i][(1 << n) - 1];
    return ans;
}

int main() {
    while(true) {
        int n = in(), m = in();
        if(make_pair(n, m) == make_pair(0, 0)) return 0;
        print(solve(n, m));
    }
}
accuracy: 1
time_ms: 5520
memory_kb: 83548
final_rank: 19

code_snippet: #line 2 "cp-library/src/cp-template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull  = unsigned long long;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
template < class T, class U > T ceil (T x, U y) { return (x > 0 ? (x + y - 1) / y :           x / y); }
template < class T, class U > T floor(T x, U y) { return (x > 0 ?           x / y : (x - y + 1) / y); }
int popcnt(i32 x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(i64 x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }

#line 2 "cp-library/src/utility/rep_itr.hpp"
template < class T > struct itr_rep {
    T i, d;
    constexpr itr_rep(const T i) noexcept : i(i), d(1) {}
    constexpr itr_rep(const T i, const T d) noexcept : i(i), d(d) {}
    void operator++() noexcept { i += d; }
    constexpr int operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr_rep x) const noexcept { return d > 0 ? i < x.i : i > x.i; }
};

template < class T > struct rep {
    const itr_rep< T > s, t;
    constexpr rep(const T t) noexcept : s(0), t(t) {}
    constexpr rep(const T s, const T t) noexcept : s(s), t(t) {}
    constexpr rep(const T s, const T t, const T d) noexcept : s(s, d), t(t, d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};

template < class T > struct revrep {
    const itr_rep < T > s, t;
    constexpr revrep(const T t) noexcept : s(t - 1, -1), t(-1, -1) {}
    constexpr revrep(const T s, const T t) noexcept : s(t - 1, -1), t(s - 1, -1) {}
    constexpr revrep(const T s, const T t, const T d) noexcept : s(t - 1, -d), t(s - 1, -d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};
#line 3 "cp-library/src/utility/io.hpp"

/* 128bit integer */
istream& operator>>(istream& is, i128& x) {
    std::string s; is >> s;
    int pm = (s[0] == '-');
    x = 0;
    for(int i : rep(pm, int(s.size()))) x = x * 10 + (s[i] - '0');
    if(pm) x *= -1;
    return is;
}
ostream& operator<<(ostream& os, const i128& x) {
    if(x == 0) return os << '0';
    i128 y = x;
    if(y < 0) { os << '-'; y *= -1; }
    std::vector<int> ny;
    while(y > 0) { ny.push_back(y % 10); y /= 10; }
    for(int i : revrep(ny.size())) os << ny[i];
    return os;
}

template < class S, class T > istream& operator>>(istream& is,       std::pair< S, T >& x) { is >> x.first        >> x.second; return is; }
template < class S, class T > ostream& operator<<(ostream& os, const std::pair< S, T >& x) { os << x.first << " " << x.second; return os; }

namespace scanner {
    struct sca {
        template < class T > operator T() {
            T s; std::cin >> s; return s;
        }
    };
    struct vec {
        int n;
        vec(int n) : n(n) {}
        template < class T > operator std::vector< T >() {
            std::vector< T > v(n);
            for(T& x : v) std::cin >> x;
            return v;
        }
    };
    struct mat {
        int h, w;
        mat(int h, int w) : h(h), w(w) {}
        template < class T > operator std::vector< std::vector< T > >() {
            std::vector m(h, std::vector< T >(w));
            for(std::vector< T >& v : m) for(T& x : v) std::cin >> x;
            return m;
        }
    };
    struct speedup {
        speedup() {
            std::cin.tie(0);
            std::ios::sync_with_stdio(0);
        }
    } speedup_instance;
}
scanner::sca in() { return scanner::sca(); }
scanner::vec in(int n) { return scanner::vec(n); }
scanner::mat in(int h, int w) { return scanner::mat(h, w); }

namespace printer {
    void precision(int d) { std::cout << std::fixed << std::setprecision(d); }
    void flush() { std::cout.flush(); }
}

template < class T >
ostream& operator<<(ostream& os, const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) { os << a[i]; if(i != n - 1) os << ' '; }
    return os;
}

int print() { std::cout << '\n'; return 0; }
template < class head, class... tail > int print(head&& h, tail&&... t) {
    std::cout << h; if(sizeof...(tail)) std::cout << ' ';
    return print(std::forward<tail>(t)...);
}
template < class T > int print_n(const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) std::cout << a[i] << "\n";
    return 0;
}


#line 2 "cp-library/src/utility/key_val.hpp"

template < class K, class V >
struct key_val {
    K key; V val;
    key_val() {}
    key_val(K key, V val) : key(key), val(val) {}
    template < std::size_t Index >
    std::tuple_element_t< Index, key_val >& get() {
        if constexpr (Index == 0) return key;
        if constexpr (Index == 1) return val;
    }
};

namespace std {

template < class K, class V > struct tuple_size < key_val< K, V > > : integral_constant< size_t, 2 > {};
template < class K, class V > struct tuple_element < 0, key_val< K, V > > { using type = K; };
template < class K, class V > struct tuple_element < 1, key_val< K, V > > { using type = V; };

}
#line 2 "cp-library/src/utility/vec_op.hpp"
template < class T > key_val< int, T > max_of(const vector< T >& a) {
    int i = std::max_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class T > key_val< int, T > min_of(const vector< T >& a) {
    int i = std::min_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class S, class T > S sum_of(const vector< T >& a) {
    S sum = 0;
    for(const T x : a) sum += x;
    return sum;
}
template < class S, class T > vector< S > freq_of(const vector< T >& a, T L, T R) {
    vector< S > res(R - L, S(0));
    for(const T x : a) res[x - L] += 1;
    return res;
}
template < class S, class T > struct prefix_sum {
    vector< S > s;
    prefix_sum(const vector< T >& a) : s(a) {
        s.insert(s.begin(), S(0));
        for(int i : rep(a.size())) s[i + 1] += s[i];
    }
    // [L, R)
    S sum(int L, int R) { return s[R] - s[L]; }
};
#line 3 "cp-library/src/utility/heap.hpp"

template < class T > using heap_min = std::priority_queue< T, std::vector< T >, std::greater< T > >;
template < class T > using heap_max = std::priority_queue< T, std::vector< T >, std::less< T > >;

#line 27 "cp-library/src/cp-template.hpp"

#line 1 "cp-library/src/algorithm/bin_search.hpp"
template < class T, class F >
T bin_search(T ok, T ng, F f) {
    while(abs(ng - ok) > 1) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template < class T, class F >
T bin_search_real(T ok, T ng, F f, int step = 80) {
    while(step--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
#line 2 "cp-library/src/algorithm/argsort.hpp"

template < class T > std::vector< int > argsort(const std::vector< T > &a) {
    std::vector< int > ids((int)a.size());
    std::iota(ids.begin(), ids.end(), 0);
    std::sort(ids.begin(), ids.end(), [&](int i, int j) {
        return a[i] < a[j] || (a[i] == a[j] && i < j);
    });
    return ids;
}
#line 1 "macro.hpp"
namespace macro {

using size_type = int;
template < class container > void  sort(container& a) { std::sort(std:: begin(a), std:: end(a)); }
template < class container > void rsort(container& a) { std::sort(std::rbegin(a), std::rend(a)); }
template < class container > void reverse(container& a) { std::reverse(std::begin(a), std::end(a)); }
template < class container > void unique(container& a) {
    std::sort(std::begin(a), std::end(a));
    a.erase(std::unique(std::begin(a), std::end(a)), std::end(a));
}
template < class container > container  sorted(const container& a) { container b = a;  sort(b); return std::move(b); }
template < class container > container rsorted(const container& a) { container b = a; rsort(b); return std::move(b); }
template < class container, class compare > void sort(container& a, const compare& cmp) { std::sort(std::begin(a), std::end(a), cmp); }
template < class container, class compare > container sorted(const container& a, const compare& cmp) { container b = a; sort(b, cmp); return std::move(b); }
template < class container, class value > size_type lower_bound(const container& a, const value& x) { return std::lower_bound(std::begin(a), std::end(a), x) - std::begin(a); }
template < class container, class value > size_type upper_bound(const container& a, const value& x) { return std::upper_bound(std::begin(a), std::end(a), x) - std::begin(a); }

const std::vector<std::pair<size_type, size_type>> dir4 = { {+1,  0}, {-1,  0}, { 0, +1}, { 0, -1} };
const std::vector<std::pair<size_type, size_type>> dir8 = { {-1, -1}, {-1,  0}, {-1, +1}, { 0, -1}, { 0, +1}, {+1, -1}, {+1,  0}, {+1, +1} };

#ifdef _DEBUG
#define debug(x) std::cout << "[" << __LINE__ << "] " << #x << ": " << x << std::endl
#else
#define debug(x)
#endif

template < class container > void concat(container& a, const container& b) {
    a.insert(std::end(a), std::begin(b), std::end(b));
}
std::vector<size_type> iota(const size_type n) {
    std::vector<size_type> I(n);
    std::iota(std::begin(I), std::end(I), 0);
    return I;
}
template < class container > std::vector<size_type> sort_idx(const container& a) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return a[i] < a[j] or (a[i] == a[j] and i < j); });
    return I;
}
template < class container, class compare > std::vector<size_type> sort_idx(const container& a, const compare& cmp) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return cmp(a[i], a[j]) or (a[i] == a[j] and i < j); });
    return std::move(I);
}

struct grid {
    using size_type = int;
    size_type H, W;
    grid(const size_type H, const size_type W) : H(H), W(W) {}
    bool contains(const size_type i, const size_type j) {
        return 0 <= i and i < H and 0 <= j and j < W;
    }
};

using f64 = long double;

template < class T > vector< T >& operator++(vector< T >& a) { for(T& x : a) x++; return a; }
template < class T > vector< T >& operator--(vector< T >& a) { for(T& x : a) x--; return a; }
template < class T > vector< T >  operator++(vector< T >& a, signed) { vector< T > res = a; for(T& x : a) x++; return res; }
template < class T > vector< T >  operator--(vector< T >& a, signed) { vector< T > res = a; for(T& x : a) x--; return res; }

} // namespace macro

using namespace macro;
#line 3 "cp-library/src/utility/random.hpp"

namespace randnum {

static uint seed;
static std::mt19937 mt;
struct gen_seed {
    gen_seed() {
        seed = std::random_device()();
        mt = std::mt19937(seed);
    }
} gs;

// [L, R)
template < class T >
T gen_int(T L, T R) {
    return std::uniform_int_distribution< T >(L, R - 1)(mt);
}

template < class T >
T get_real(T L, T R) {
    return std::uniform_real_distribution< T >(L, R)(mt);
}

}
#line 3 "cp-library/src/utility/hash.hpp"

template < int num_of_mod = 2 >
struct hash_vector : public array<ll, num_of_mod> {
    //static constexpr ll MODS[] = {999999937, 1000000007, 1000000009, 1000000021};
    static constexpr ll MODS[] = {1000000021, 999999937, 1000000007, 1000000009, };
    static_assert(1 <= num_of_mod and num_of_mod <= 4);
    using array<ll, num_of_mod>::operator[];
    using H = hash_vector;
    static constexpr int n = num_of_mod;
    hash_vector() : array<ll,n>() {}
    hash_vector(ll x) : H() { for(int i : rep(n)) (*this)[i] = x % MODS[i]; }
    H& operator+=(const H& rhs) { for(int i : rep(n)) if(((*this)[i] += rhs[i]) >= MODS[i]) (*this)[i] -= MODS[i]; return *this; }
    H& operator-=(const H& rhs) { for(int i : rep(n)) if(((*this)[i] += MODS[i] - rhs[i]) >= MODS[i]) (*this)[i] -= MODS[i]; return *this; }
    H& operator*=(const H& rhs) { for(int i : rep(n)) (*this)[i] = (*this)[i] * rhs[i] % MODS[i]; return *this; }
    H& operator+=(const ll rhs) { for(int i : rep(n)) if(((*this)[i] += rhs % MODS[i]) >= MODS[i]) (*this)[i] -= MODS[i]; return *this; }
    H& operator-=(const ll rhs) { for(int i : rep(n)) if(((*this)[i] += MODS[i] - rhs % MODS[i]) >= MODS[i]) (*this)[i] -= MODS[i]; return *this; }
    H& operator*=(const ll rhs) { for(int i : rep(n)) (*this)[i] = (*this)[i] * (rhs % MODS[i]) % MODS[i]; return *this; }
    H operator+(const H& rhs) const { return H(*this) += rhs; }
    H operator-(const H& rhs) const { return H(*this) -= rhs; }
    H operator*(const H& rhs) const { return H(*this) *= rhs; }
    H operator+(const ll rhs) const { return H(*this) += rhs; }
    H operator-(const ll rhs) const { return H(*this) -= rhs; }
    H operator*(const ll rhs) const { return H(*this) *= rhs; }
    H operator-() const { return H().fill(0) - *this; }
    friend H operator+(ll x, const H& y) { return H(x) + y; }
    friend H operator-(ll x, const H& y) { return H(x) + y; }
    friend H operator*(ll x, const H& y) { return H(x) * y; }
    bool operator==(const H& rhs) { for(int i : rep(n)) if((*this)[i] != rhs[i]) return false; return true ; }
    bool operator!=(const H& rhs) { for(int i : rep(n)) if((*this)[i] != rhs[i]) return true ; return false; }
};
#line 4 "cp-library/src/string/rolling_hash.hpp"


constexpr ll BASE = 10007;
template< int num_of_mod = 2 >
struct rolling_hash {

    static const ll BASE;

    vector< hash_vector< num_of_mod > > pb, hs;
    rolling_hash() {}
    rolling_hash(const string& s) {
        int n = s.size();
        hs.resize(n + 1); hs[0].fill(0);
        pb.resize(n + 1); pb[0].fill(1);
        for(int i : rep(n)) {
            hs[i + 1] = hs[i] * BASE + s[i];
            pb[i + 1] = pb[i] * BASE;
        }
    }

    // [l, r)
    hash_vector< num_of_mod > get(int l, int r) const {
        return hs[r] - hs[l] * pb[r - l];
    }

    hash_vector< num_of_mod > concat(hash_vector< num_of_mod > h1, hash_vector< num_of_mod > h2, int h2_len) {
        assert(0 <= h2_len and h2_len < int(pb.size()));
        return h1 * pb[h2_len] + h2;
    }

    template < int n >
    static int lcp(const rolling_hash< n >& rh1, int l1, int r1, const rolling_hash< n >& rh2, int l2, int r2) {
        int lo = -1, hi = min(r1 - l1, r2 - l2) + 1;
        while(hi - lo > 1) {
            int mid = (lo + hi) / 2;
            (rh1.get(l1, l1 + mid) == rh2.get(l2, l2 + mid) ? lo : hi) = mid;
        }
        return lo;
    }

    template < int n >
    static int cmp(const string& s1, const rolling_hash< n >& rh1, int l1, int r1,
                   const string& s2, const rolling_hash< n >& rh2, int l2, int r2) {
        int len = lcp(rh1, l1, r1, rh2, l2, r2);
        if(len == r1 - l1 && len == r2 - l2) return 0;
        if(len == r1 - l1) return -1;
        if(len == r2 - l2) return +1;
        return (s1[l1 + len] < s2[l2 + len] ? -1 : +1);
    }
};

template < int num_of_mod >
const ll rolling_hash< num_of_mod >::BASE = randnum::gen_int<ll>(ll(0), hash_vector< num_of_mod >::MODS[0]);
#line 4 "A.cpp"
using RH = rolling_hash< 2 >;

int solve(int n, int m) {
    vector<string> e = in(n);
    vector<RH> he(n);
    for(int i : rep(n)) he[i] = RH(e[i]);

    int ans = 0;
    string t = "";
    for(int _ : rep(m)) { string s = in(); t += s; }
    const int sz_t = t.size();
    RH ht(t);
    vector dp(sz_t + 1, vector(1 << n, int(0)));
    for(int i : rep(sz_t + 1)) dp[i][0] = 1;
    for(int i : rep(sz_t + 1)) {
        for(int S : rep(1 << n)) if(dp[i][S]) {
            for(int k : rep(n)) {
                if((S >> k & 1) == 0) {
                    const int sz_e = e[k].size();
                    if(i + sz_e <= sz_t and ht.get(i, i + sz_e) == he[k].get(0, sz_e)) {
                        dp[i + sz_e][S | (1 << k)] = 1;
                    }
                }
            }
        }
    }
    for(int i : rep(sz_t + 1)) ans += dp[i][(1 << n) - 1];
    return ans;
}

int main() {
    while(true) {
        int n = in(), m = in();
        if(make_pair(n, m) == make_pair(0, 0)) return 0;
        print(solve(n, m));
    }
}
accuracy: 1
time_ms: 5590
memory_kb: 83540
final_rank: 20

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

int main() {
    int MAXS = 20;
while(1) {
    int N, Q;
    cin >> N >> Q;
    if (N == 0) return 0;
    vector<string> S(N);
    rep(i,0,N) cin >> S[i];
    string T;
    while(Q--) {
        string U;
        cin >> U;
        T += U;
    }
    int M = T.size();
    vector DP(M+1, vector<bool>(1<<N,false));
    rep(i,0,M) {
        DP[i][0] = true;
        vector<bool> B(N,false);
        rep(j,0,N) {
            if (i+S[j].size() <= T.size() && T.substr(i,S[j].size()) == S[j]) B[j] = true;
        }
        rep(j,0,1<<N) {
            if (!DP[i][j]) continue;
            rep(k,0,N) {
                if (j & (1<<k)) continue;
                if (B[k]) DP[i+S[k].size()][j|(1<<k)] = true;
            }
        }
    }
    int ANS = 0;
    rep(i,0,M+1) if (DP[i][(1<<N)-1]) ANS++;
    cout << ANS << endl;
}
}
accuracy: 1
time_ms: 2560
memory_kb: 5892
final_rank: 10

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll=long long;

int N,M;
void solve(){
    vector<string> S(N);
    string T="";
    for(int i=0;i<N;i++)cin>>S[i];
    int K=0;
    for(int m=0;m<M;m++){
        string t;
        cin>>t;
        T+=t;
        K+=t.size();
    }
    vector<vector<bool>> DP(K+1,vector<bool>(1<<N,0));
    DP[0][0]=1;
    for(int k=0;k<K;k++){
        vector<bool> OK(N,0);
        for(int i=0;i<N;i++)if(T.substr(k,S[i].size())==S[i])OK[i]=1;
        DP[k][0]=1;
        for(int bit=0;bit<(1<<N);bit++){
            if(!DP[k][bit])continue;
            for(int b=0;b<N;b++){
                if(bit&(1<<b))continue;
                if(!OK[b])continue;
                DP[k+S[b].size()][bit+(1<<b)]=1;
            }
        }
    }
    int an=0;
    for(int i=0;i<=K;i++)an+=DP[i][(1<<N)-1];
    cout<<an<<endl;

}

int main() {
    while(cin>>N>>M,N+M!=0)solve();
    
}
accuracy: 1
time_ms: 2580
memory_kb: 5660
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define rep(i, x, y) for (int i = (x); i < (y); ++i)

const int inf = 1e9;
const int64_t inf64 = 1e18;
const double eps = 1e-9;

void solve(int n, int m) {
  vector<string> e(n);
  stringstream ss;
  rep(i, 0, n) {
    cin >> e[i];
  }
  rep(i, 0, m) {
    string t;
    cin >> t;
    ss << t;
  }
  string ts = ss.str();

  vector<int> sum_len(1 << n);
  rep(i, 0, 1 << n) {
    rep(j, 0, n) {
      if (((i >> j) & 1) == 0) continue;
      sum_len[i] += e[j].size();
    }
  }

  vector<vector<bool>> p(5000, vector<bool>(1 << 12, false));
  vector<vector<int>> heads(ts.size());
  rep(i, 0, ts.size()) p[i][0] = true;
  rep(i, 0, ts.size()) {
    rep(j, 0, n) {
      if (i + e[j].size() > ts.size() or !equal(e[j].begin(), e[j].end(), ts.begin() + i)) continue;
      p[i][1 << j] = true;
      heads[i].push_back(j);
    }
  }

  int ans = 0;
  for (int i = ts.size() - 1; i >= 0; --i) {
    rep(j, 1, 1 << n) {
      if (p[i][j] or i + sum_len[j] > ts.size()) continue;
      for (int k : heads[i]) {
        if (((j >> k) & 1) == 0) continue;
        int i2 = i + e[k].size();
        if (p[i2][j & (~(1 << k))]) {
          p[i][j] = true;
          break;
        }
      }
    }
    if (p[i][(1 << n) - 1]) ++ans;
  }
  cout << ans << endl;
}

int main() {
  std::cin.tie(0);
  std::ios::sync_with_stdio(false);
  cout.setf(ios::fixed);
  cout.precision(10);
  for (;;) {
    int n, m;
    cin >> n >> m;
    if (n == 0 and m == 0) break;
    solve(n, m);
  }
  return 0;
}
accuracy: 1
time_ms: 1760
memory_kb: 6676
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, x, y) for (int i = (x); i < (y); ++i)
#define debug(x) #x << "=" << (x)
#ifdef DEBUG
#define _GLIBCXX_DEBUG
#define print(x) std::cerr << debug(x) << " (L:" << __LINE__ << ")" << std::endl
#else
#define print(x)
#endif
const int inf = 1e9;
const int64_t inf64 = 1e18;
const double eps = 1e-9;
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
  os << "[";
  for (const auto &v : vec) {
    os << v << ",";
  }
  os << "]";
  return os;
}
void solve(int n, int m) {
  vector<string> e(n);
  string ts;
  int concatenated_len = 0;
  rep(i, 0, n) {
    cin >> e[i];
    concatenated_len += e[i].size();
  }
  rep(i, 0, m) {
    string t;
    cin >> t;
    ts += t;
  }
  vector<int> sum_len(1 << n);
  rep(i, 0, 1 << n) {
    for (int j = 0; j < n; ++j) {
      if (i & (1 << j)) {
        sum_len[i] += e[j].size();
      }
    }
  }
  static bool p[5000][1 << 12];
  fill_n((bool *)p, 5000 * (1 << 12), false);
  vector<vector<int>> heads(ts.size());
  rep(i, 0, ts.size()) p[i][0] = true;
  rep(i, 0, ts.size()) {
    for (int j = 0; j < n; ++j) {
      if (i + e[j].size() <= ts.size() && e[j] == ts.substr(i, e[j].size())) {
        p[i][1 << j] = true;
        heads[i].push_back(j);
      }
    }
  }
  int ans = 0;
  for (int i = ts.size() - 1; i >= 0; --i) {
    for (int j = 1; j < (1 << n); ++j) {
      if (p[i][j] || i + sum_len[j] > ts.size()) continue;
      for (int k : heads[i]) {
        if (j & (1 << k)) {
          int i2 = i + e[k].size();
          if (p[i2][j ^ (1 << k)]) { //Use bitwise XOR to get the remaining subset
            p[i][j] = true;
            break;
          }
        }
      }
    }
    if (p[i][(1 << n) - 1])
      ++ans;
  }
  cout << ans << endl;
}
int main() {
  std::cin.tie(0);
  std::ios::sync_with_stdio(false);
  cout.setf(ios::fixed);
  cout.precision(10);
  for (;;) {
    int n, m;
    cin >> n >> m;
    if (n == 0 and m == 0)
      break;
    solve(n, m);
  }
  return 0;
}
accuracy: 1
time_ms: 1350
memory_kb: 23896
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, x, y) for (int i = (x); i < (y); ++i)
#define debug(x) #x << "=" << (x)
#ifdef DEBUG
#define _GLIBCXX_DEBUG
#define print(x) std::cerr << debug(x) << " (L:" << __LINE__ << ")" << std::endl
#else
#define print(x)
#endif
const int inf = 1e9;
const int64_t inf64 = 1e18;
const double eps = 1e-9;
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
  os << "[";
  for (const auto &v : vec) {
    os << v << ",";
  }
  os << "]";
  return os;
}
void solve(int n, int m) {
  vector<string> e(n);
  string ts;
  int concatenated_len = 0;
  rep(i, 0, n) {
    cin >> e[i];
    concatenated_len += e[i].size();
  }
  rep(i, 0, m) {
    string t;
    cin >> t;
    ts += t;
  }
  vector<int> sum_len(1 << n);

  vector<vector<bool>> p(ts.size(), vector<bool>(1 << n, false)); // Optimized data structure

  vector<vector<int>> heads(ts.size());
  rep(i, 0, ts.size()) p[i][0] = true;
  rep(i, 0, ts.size()) {
    rep(j, 0, n) {
      if (i + e[j].size() > ts.size() or e[j] != ts.substr(i, e[j].size()))
        continue;
      p[i][1 << j] = true;
      heads[i].push_back(j);
    }
  }
  int ans = 0;
  for (int i = ts.size() - 1; i >= 0; --i) {
    rep(j, 1, 1 << n) {
      if (p[i][j])
        continue;

      //Calculate sum_len on demand
      if (sum_len[j] == 0) {
        rep(k, 0, n) {
          if (((j >> k) & 1) != 0)
            sum_len[j] += e[k].size();
        }
      }

      if (i + sum_len[j] > ts.size())
        continue;

      for (int k : heads[i]) {
        if (((j >> k) & 1) == 0)
          continue;
        int i2 = i + e[k].size();
        if (p[i2][j & (~(1 << k))]) {
          p[i][j] = true;
          break;
        }
      }
    }
    if (p[i][(1 << n) - 1])
      ++ans;
  }
  cout << ans << endl;
}
int main() {
  std::cin.tie(0);
  std::ios::sync_with_stdio(false);
  cout.setf(ios::fixed);
  cout.precision(10);
  for (;;) {
    int n, m;
    cin >> n >> m;
    if (n == 0 and m == 0)
      break;
    solve(n, m);
  }
  return 0;
}
accuracy: 1
time_ms: 1710
memory_kb: 6544
final_rank: 2

code_snippet: #include <algorithm>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <vector>
using namespace std;
typedef long long ll;
typedef pair<int, int> PI;
#define EPS (1e-6)
#define rep(i, n) for (int i = 0; i < (int)(n); ++i)
#define REP(i, n) rep(i, n)
#define F first
#define S second
#define mp(a, b) make_pair(a, b)
#define pb(a) push_back(a)
#define min3(a, b, c) min((a), min((b), (c)))
#define min4(a, b, c, d) min((a), min3((b), (c), (d)))
#define SZ(a) (int)((a).size())
#define ALL(a) (a).begin(), (a).end()
#define RALL(a) a.rbegin(), a.rend()
#define FLL(a, b) memset((a), b, sizeof(a))
#define CLR(a) memset((a), 0, sizeof(a))
#define declare(a, it) __typeof(a) it = (a)
#define FOR(it, a) for (declare(a.begin(), it); it != a.end(); ++it)
#define FORR(it, a) for (declare(a.rbegin(), it); it != a.rend(); ++it)
template <typename T, typename U>
ostream &operator<<(ostream &out, const pair<T, U> &val) {
  return out << "(" << val.F << ", " << val.S << ")";
}
template <class T> ostream &operator<<(ostream &out, const vector<T> &val) {
  out << "{";
  rep(i, SZ(val)) out << (i ? ", " : "") << val[i];
  return out << "}";
}
typedef double FP;
typedef complex<FP> pt;
typedef pt P;
typedef pair<pt, pt> line;
namespace std {
bool operator<(const P &a, const P &b) {
  if (abs(a.real() - b.real()) > EPS)
    return a.real() < b.real();
  return a.imag() < b.imag();
}
} // namespace std
FP dot(P a, P b) { return real(conj(a) * b); }
FP crs(P a, P b) { return imag(conj(a) * b); }
P ortho(P a) { return P(imag(a), -real(a)); }
P ortho(line a) { return ortho(a.S - a.F); }
P crspt(P a, P b, P c, P d) {
  b -= a, d -= c;
  return a + b * crs(d, c - a) / crs(d, b);
}
P crspt(line a, line b) { return crspt(a.F, a.S, b.F, b.S); }
bool onl(P a1, P a2, P b) {
  return abs(b - a1) + abs(b - a2) < abs(a1 - a2) + EPS;
}
bool onl(line a, P b) { return onl(a.F, a.S, b); }
bool iscrs(line a, line b) {
  P c = crspt(a, b);
  return onl(a, c) && onl(b, c);
}
void pkuassert(bool t) { t = 1 / t; };
int dx[] = {0, 1, 0, -1, 1, 1, -1, -1};
int dy[] = {1, 0, -1, 0, -1, 1, 1, -1};
enum { TOP, BTM, LFT, RGT, FRT, BCK };
int dxdy2ce[] = {RGT, FRT, LFT, BCK};
int s2i(string &a) {
  stringstream ss(a);
  int r;
  ss >> r;
  return r;
}
template <class T> T shift(T a, int b, int c, int d, int e) {
  __typeof(a[0]) t = a[b];
  a[b] = a[c];
  a[c] = a[d];
  a[d] = a[e];
  a[e] = t;
  return a;
}
template <class T> T rgt(T a) { return shift(a, TOP, LFT, BTM, RGT); }
template <class T> T lft(T a) { return shift(a, TOP, RGT, BTM, LFT); }
template <class T> T frt(T a) { return shift(a, TOP, BCK, BTM, FRT); }
template <class T> T bck(T a) { return shift(a, TOP, FRT, BTM, BCK); }
line mkl(P a, P v) { return line(a, a + v); }
FP lpdist(line a, P b) { return abs(b - crspt(a, mkl(b, ortho(a)))); }
FP spdist(line a, P b) {
  P c(crspt(a, mkl(b, ortho(a))));
  return onl(a, c) ? abs(b - c) : min(abs(a.F - b), abs(a.S - b));
}
FP ssdist(line a, line b) {
  return iscrs(a, b) ? 0.
                     : min4(spdist(a, b.F), spdist(a, b.S), spdist(b, a.F),
                            spdist(b, a.S));
}
int n, m;
ll gha[6000];
bool vis[1 << 12][100];
ll po[1000];
void solve() {
  ll ha[n];
  int len[n];
  rep(i, n) {
    string a;
    cin >> a;
    ll h = 0;
    len[i] = SZ(a);
    FOR(it, a)
    h = h * 31 + *it;
    ha[i] = h;
  }
  po[0] = 1;
  rep(i, 999) po[i + 1] = po[i] * 31;
  int ans = 0;
  string text;
  rep(jjj, m) {
    string a;
    cin >> a;
    text += a;
  }
  int len_text = SZ(text);
  rep(i, len_text) gha[i + 1] = gha[i] * 31 + text[i];
  bool vis[250][1 << n];
  rep(i, 250) rep(j, 1 << n) vis[i][j] = 0;
  rep(i, 250) vis[i][0] = 1;
  rep(j, len_text + 1) {
    int cur = j % 250;
    rep(i, 1 << n) {
      if (!vis[cur][i])
        continue;
      rep(k, n) {
        ll calc = gha[j + len[k]] - gha[j] * po[len[k]];
        if ((~i & (1 << k)) && len[k] + j <= len_text && ha[k] == calc)
          vis[(j + len[k]) % 250][i | (1 << k)] = 1;
      }
    }
    ans += vis[cur][(1 << n) - 1];
    rep(i, 1 << n) vis[cur][i] = 0;
    vis[cur][0] = 1;
  }
  cout << ans << endl;
  return;
}
int main(int argc, char *argv[]) {
  while (cin >> n >> m, n)
    solve();
  return 0;
}
accuracy: 1
time_ms: 3190
memory_kb: 4512
final_rank: 17

code_snippet: #include <algorithm>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <sstream>

typedef long long ll;
typedef std::pair<int, int> PI;

ll gha[6000];
ll po[1000];

void solve(int n, int m, ll *gha) {
  ll ha[n];
  int len[n];
  for (int i = 0; i < n; ++i) {
    std::string a;
    std::cin >> a;
    ll h = 0;
    len[i] = a.size();
    for (char it : a)
      h = h * 31 + it;
    ha[i] = h;
  }
  po[0] = 1;
  for (int i = 0; i < 999; i++) po[i + 1] = po[i] * 31;
  int ans = 0;
  std::string text;
  for (int jjj = 0; jjj < m; jjj++) {
    std::string a;
    std::cin >> a;
    text += a;
  }
  for (int i = 0; i < text.size(); i++) gha[i + 1] = gha[i] * 31 + text[i];
  bool vis[250][1 << n];
  for (int i = 0; i < 250; i++) for (int j = 0; j < (1 << n); j++) vis[i][j] = 0;
  for (int i = 0; i < 250; i++) vis[i][0] = 1;
  for (int j = 0; j < text.size() + 1; j++) {
    int cur = j % 250;
    for (int i = 0; i < (1 << n); i++) {
      if (!vis[cur][i])
        continue;
      for (int k = 0; k < n; k++) {
        if ((~i & (1 << k)) && len[k] + j <= text.size() && ha[k] == gha[j + len[k]] - gha[j] * po[len[k]])
          vis[(j + len[k]) % 250][i | (1 << k)] = 1;
      }
    }
    ans += vis[cur][(1 << n) - 1];
    for (int i = 0; i < (1 << n); i++) vis[cur][i] = 0;
    vis[cur][0] = 1;
  }
  std::cout << ans << std::endl;
  return;
}

int main(int argc, char *argv[]) {
  int n, m;
  while (std::cin >> n >> m, n)
    solve(n, m, gha);
  return 0;
}
accuracy: 1
time_ms: 2810
memory_kb: 4416
final_rank: 14

code_snippet: #include <algorithm>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <vector>
using namespace std;
typedef long long ll;
typedef pair<int, int> PI;
typedef double FP;
typedef complex<FP> pt;
typedef pt P;
typedef pair<pt, pt> line;

int main(int argc, char *argv[]) {
  ll n, m;
  while (cin >> n >> m, n) {
    ll ha[n];
    int len[n];
    for(int i = 0; i < n; ++i) {
      string a;
      cin >> a;
      ll h = 0;
      len[i] = a.size();
      for(char& c : a)
        h = h * 31 + c;
      ha[i] = h;
    }
    ll po[1000];
    po[0] = 1;
    for(int i = 0; i < 999; ++i) po[i + 1] = po[i] * 31;
    int ans = 0;
    string text;
    for(int jjj = 0; jjj < m; ++jjj) {
      string a;
      cin >> a;
      text += a;
    }
    ll gha[6000];
    for(int i = 0; i < text.size(); ++i) gha[i + 1] = gha[i] * 31 + text[i];
    bool vis[250][1 << n];
    for(int i = 0; i < 250; ++i) for(int j = 0; j < 1 << n; ++j) vis[i][j] = 0;
    for(int i = 0; i < 250; ++i) vis[i][0] = 1;
    for(int j = 0; j < text.size() + 1; ++j) {
      int cur = j % 250;
      for(int i = 0; i < 1 << n; ++i) {
        if (!vis[cur][i])
          continue;
        for(int k = 0; k < n; ++k) if ((~i & (1 << k)) && len[k] + j <= text.size() &&
          ha[k] == gha[j + len[k]] - gha[j] * po[len[k]])
          vis[(j + len[k]) % 250][i | (1 << k)] = 1;
      }
      ans += vis[cur][(1 << n) - 1];
      for(int i = 0; i < 1 << n; ++i) vis[cur][i] = 0;
      vis[cur][0] = 1;
    }
    cout << ans << "\n";
  }
  return 0;
}
accuracy: 1
time_ms: 2490
memory_kb: 4340
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, x, y) for (int i = (x); i < (y); ++i)
#define debug(x) #x << "=" << (x)
#ifdef DEBUG
#define _GLIBCXX_DEBUG
#define print(x) std::cerr << debug(x) << " (L:" << __LINE__ << ")" << std::endl
#else
#define print(x)
#endif
const int inf = 1e9;
const int64_t inf64 = 1e18;
const double eps = 1e-9;
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
  os << "[";
  for (const auto &v : vec) {
    os << v << ",";
  }
  os << "]";
  return os;
}
void solve(int n, int m) {
  vector<string> e(n);
  string ts;
  int concatenated_len = 0;
  rep(i, 0, n) {
    cin >> e[i];
    concatenated_len += e[i].size();
  }
  ts.reserve(m); // reserve memory for string
  rep(i, 0, m) {
    string t;
    cin >> t;
    ts += t;
  }
  vector<int> sum_len(1 << n);
  rep(i, 0, 1 << n) {
    rep(j, 0, n) {
      if (((i >> j) & 1) == 0)
        continue;
      sum_len[i] += e[j].size();
    }
  }
  static bool p[5000][1 << 12];
  fill_n((bool *)p, 5000 * (1 << 12), false);
  vector<vector<int>> heads(ts.size());
  rep(i, 0, ts.size()) p[i][0] = true;
  rep(i, 0, ts.size()) {
    rep(j, 0, n) {
      if (i + e[j].size() > ts.size() or !equal(e[j].begin(), e[j].end(), ts.begin() + i))
        continue;
      p[i][1 << j] = true;
      heads[i].push_back(j);
    }
  }
  int ans = 0;
  for (int i = ts.size() - 1; i >= 0; --i) {
    rep(j, 1, 1 << n) {
      if (p[i][j] or i + sum_len[j] > ts.size())
        continue;
      for (int k : heads[i]) {
        if (((j >> k) & 1) == 0)
          continue;
        int i2 = i + e[k].size();
        if (p[i2][j & (~(1 << k))]) {
          p[i][j] = true;
          break;
        }
      }
    }
    if (p[i][(1 << n) - 1])
      ++ans;
  }
  cout << ans << endl;
}
int main() {
  std::cin.tie(0);
  std::ios::sync_with_stdio(false);
  cout.setf(ios::fixed);
  cout.precision(10);
  for (;;) {
    int n, m;
    cin >> n >> m;
    if (n == 0 and m == 0)
      break;
    solve(n, m);
  }
  return 0;
}
accuracy: 1
time_ms: 1450
memory_kb: 23684
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define rep(i, x, y) for (int i = (x); i < (y); ++i)
#define debug(x) #x << "=" << (x)

#ifdef DEBUG
#define _GLIBCXX_DEBUG
#define print(x) std::cerr << debug(x) << " (L:" << __LINE__ << ")" << std::endl
#else
#define print(x)
#endif

const int inf = 1e9;
const int64_t inf64 = 1e18;
const double eps = 1e-9;

template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
  os << "[";
  for (const auto &v : vec) {
    os << v << ",";
  }
  os << "]";
  return os;
}

void solve(int n, int m) {
  vector<string> e(n);
  string ts;
  int concatenated_len = 0;
  rep(i, 0, n) {
    cin >> e[i];
    concatenated_len += e[i].size();
  }
  rep(i, 0, m) {
    string t;
    cin >> t;
    ts += t;
  }
  vector<int> sum_len(1 << n);
  rep(i, 0, 1 << n) {
    rep(j, 0, n) {
      if (((i >> j) & 1) == 0)
        continue;
      sum_len[i] += e[j].size();
    }
  }
  static bool p[5000][1 << 12];
  fill_n((bool *)p, 5000 * (1 << 12), false);
  
  int ts_size = ts.size();
  
  vector<vector<int>> heads(ts_size);
  heads.reserve(ts_size); // preallocate memory
  
  rep(i, 0, ts_size) p[i][0] = true;
  rep(i, 0, ts_size) {
    rep(j, 0, n) {
      if (i + e[j].size() > ts_size || e[j].compare(0, e[j].size(), ts, i, e[j].size()) != 0)
        continue;
      p[i][1 << j] = true;
      heads[i].push_back(j);
    }
  }
  int ans = 0;
  for (int i = ts_size - 1; i >= 0; --i) {
    rep(j, 1, 1 << n) {
      if (p[i][j] or i + sum_len[j] > ts_size)
        continue;
      for (int k : heads[i]) {
        if (((j >> k) & 1) == 0)
          continue;
        int i2 = i + e[k].size();
        if (p[i2][j & (~(1 << k))]) {
          p[i][j] = true;
          break;
        }
      }
    }
    if (p[i][(1 << n) - 1])
      ++ans;
  }
  cout << ans << '\n'; // use '\n' instead of std::endl
}

int main() {
  std::cin.tie(0);
  std::ios::sync_with_stdio(false);
  cout.setf(ios::fixed);
  cout.precision(10);
  for (;;) {
    int n, m;
    cin >> n >> m;
    if (n == 0 and m == 0)
      break;
    solve(n, m);
  }
  return 0;
}
accuracy: 1
time_ms: 1510
memory_kb: 23900
final_rank: 8

code_snippet: #include <iostream>
#include <vector>
#include <string.h>

#define rep(i, x, y) for (int i = (x); i < (y); ++i)
#define debug(x) #x << "=" << (x)
#ifdef DEBUG
#define _GLIBCXX_DEBUG
#define print(x) std::cerr << debug(x) << " (L:" << __LINE__ << ")" << std::endl
#else
#define print(x)
#endif
const int inf = 1e9;
const int64_t inf64 = 1e18;
const double eps = 1e-9;

void solve(int n, int m) {
  std::vector<std::string> e(n);
  std::string ts;
  ts.reserve(m); // Reserve memory for ts
  rep(i, 0, n) {
    std::cin >> e[i];
  }
  rep(i, 0, m) {
    std::string t;
    std::cin >> t;
    ts += t;
  }
  std::vector<int> sum_len(1 << n);
  rep(i, 0, 1 << n) {
    rep(j, 0, n) {
      if (((i >> j) & 1) == 0)
        continue;
      sum_len[i] += e[j].size();
    }
  }
  static bool p[5000][1 << 12];
  memset(p, false, sizeof(p)); // Use memset to initialize the boolean array
  std::vector<std::vector<int>> heads(ts.size());
  rep(i, 0, ts.size()) p[i][0] = true;
  rep(i, 0, ts.size()) {
    rep(j, 0, n) {
      if (i + e[j].size() > ts.size() or e[j] != ts.substr(i, e[j].size()))
        continue;
      p[i][1 << j] = true;
      heads[i].push_back(j);
    }
  }
  int ans = 0;
  for (int i = ts.size() - 1; i >= 0; --i) {
    rep(j, 1, 1 << n) {
      if (p[i][j] or i + sum_len[j] > ts.size())
        continue;
      for (int k : heads[i]) {
        if (((j >> k) & 1) == 0)
          continue;
        int i2 = i + e[k].size();
        if (p[i2][j & (~(1 << k))]) {
          p[i][j] = true;
          break;
        }
      }
    }
    if (p[i][(1 << n) - 1])
      ++ans;
  }
  std::cout << ans << std::endl;
}
int main() {
  std::cin.tie(0);
  std::ios::sync_with_stdio(false);
  std::cout.setf(std::ios::fixed);
  std::cout.precision(10);
  for (;;) {
    int n, m;
    std::cin >> n >> m;
    if (n == 0 and m == 0)
      break;
    solve(n, m);
  }
  return 0;
}
accuracy: 1
time_ms: 1610
memory_kb: 23764
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, x, y) for (int i = (x); i < (y); ++i)
#define debug(x) #x << "=" << (x)
#ifdef DEBUG
#define _GLIBCXX_DEBUG
#define print(x) std::cerr << debug(x) << " (L:" << __LINE__ << ")" << std::endl
#else
#define print(x)
#endif
const int inf = 1e9;
const int64_t inf64 = 1e18;
const double eps = 1e-9;
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
  os << "[";
  for (const auto &v : vec) {
    os << v << ",";
  }
  os << "]";
  return os;
}
void solve(int n, int m) {
  vector<string> e(n);
  stringstream ssts; // replace with stringstream
  int concatenated_len = 0;
  rep(i, 0, n) {
    cin >> e[i];
    concatenated_len += e[i].size();
  }
  rep(i, 0, m) {
    string t;
    cin >> t;
    ssts << t; // use stringstream for concatenation
  }
  string ts = ssts.str(); // convert stringstream to string
  vector<int> sum_len(1 << n);
  rep(i, 0, 1 << n) {
    rep(j, 0, n) {
      if (((i >> j) & 1) == 0)
        continue;
      sum_len[i] += e[j].size();
    }
  }
  static bool p[5000][1 << 12];
  fill_n((bool *)p, 5000 * (1 << 12), false);
  vector<vector<int>> heads(ts.size());
  rep(i, 0, ts.size()) p[i][0] = true;
  rep(i, 0, ts.size()) {
    rep(j, 0, n) {
      if (i + e[j].size() > ts.size() or !equal(e[j].begin(), e[j].end(), ts.begin() + i))
        continue;
      p[i][1 << j] = true;
      heads[i].push_back(j);
    }
  }
  int ans = 0;
  for (int i = ts.size() - 1; i >= 0; --i) {
    rep(j, 1, 1 << n) {
      if (p[i][j] or i + sum_len[j] > ts.size())
        continue;
      for (int k : heads[i]) {
        if (((j >> k) & 1) == 0)
          continue;
        int i2 = i + e[k].size();
        if (p[i2][j & (~(1 << k))]) {
          p[i][j] = true;
          break;
        }
      }
    }
    if (p[i][(1 << n) - 1])
      ++ans;
  }
  cout << ans << endl;
}
int main() {
  std::cin.tie(0);
  std::ios::sync_with_stdio(false);
  cout.setf(ios::fixed);
  cout.precision(10);
  for (;;) {
    int n, m;
    cin >> n >> m;
    if (n == 0 and m == 0)
      break;
    solve(n, m);
  }
  return 0;
}
accuracy: 1
time_ms: 1530
memory_kb: 23812
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, x, y) for (int i = (x); i < (y); ++i)
#define debug(x) #x << "=" << (x)
#ifdef DEBUG
#define _GLIBCXX_DEBUG
#define print(x) std::cerr << debug(x) << " (L:" << __LINE__ << ")" << std::endl
#else
#define print(x)
#endif
const int inf = 1e9;
const int64_t inf64 = 1e18;
const double eps = 1e-9;
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
  os << "[";
  for (const auto &v : vec) {
    os << v << ",";
  }
  os << "]";
  return os;
}
void solve(int n, int m, vector<string> &e, string &ts) {
  int concatenated_len = 0;
  rep(i, 0, n) {
    concatenated_len += e[i].size();
  }
  vector<int> sum_len(1 << n);
  static bool p[5000][1 << 12];
  fill_n((bool *)p, 5000 * (1 << 12), false);
  vector<vector<int>> heads(ts.size());
  rep(i, 0, ts.size()) p[i][0] = true;
  rep(i, 0, ts.size()) {
    rep(j, 0, n) {
      if (i + e[j].size() > ts.size() or e[j] != ts.substr(i, e[j].size()))
        continue;
      p[i][1 << j] = true;
      heads[i].push_back(j);
    }
  }
  int ans = 0;
  for (int i = ts.size() - 1; i >= 0; --i) {
    rep(j, 1, 1 << n) {
      if (p[i][j])
        continue;
      if (sum_len[j] == 0) {
        rep(k, 0, n) {
          if (((j >> k) & 1) == 0)
            continue;
          sum_len[j] += e[k].size();
        }
      }
      if (i + sum_len[j] > ts.size())
        continue;
      for (int k : heads[i]) {
        if (((j >> k) & 1) == 0)
          continue;
        int i2 = i + e[k].size();
        if (p[i2][j & (~(1 << k))]) {
          p[i][j] = true;
          break;
        }
      }
    }
    if (p[i][(1 << n) - 1])
      ++ans;
  }
  cout << ans << endl;
}
int main() {
  std::cin.tie(0);
  std::ios::sync_with_stdio(false);
  cout.setf(ios::fixed);
  cout.precision(10);
  for (;;) {
    int n, m;
    cin >> n >> m;
    if (n == 0 and m == 0)
      break;
    vector<string> e(n);
    string ts;
    for(auto &s : e)
      cin >> s;
    for(int i = 0; i < m; i++){
      string t;
      cin >> t;
      ts += t;
    }
    solve(n, m, e, ts);
  }
  return 0;
}
accuracy: 1
time_ms: 1650
memory_kb: 23876
final_rank: 13

code_snippet: #include <iostream>
#include <string>
#include <vector>
using namespace std;

int n, m;
vector<long long> gha;

void solve() {
  vector<long long> ha(n);
  vector<int> len(n);
  for (int i = 0; i < n; ++i) {
    string a;
    cin >> a;
    long long h = 0;
    len[i] = a.size();
    for (char c : a) {
      h = h * 31 + c;
    }
    ha[i] = h;
  }

  vector<long long> po(1000);
  po[0] = 1;
  for (int i = 0; i < 999; ++i) {
    po[i + 1] = po[i] * 31;
  }

  int ans = 0;
  string text;
  for (int jjj = 0; jjj < m; ++jjj) {
    string a;
    cin >> a;
    text += a;
  }

  gha.resize(text.size() + 1);
  for (int i = 0; i < text.size(); ++i) {
    gha[i + 1] = gha[i] * 31 + text[i];
  }

  vector<vector<bool>> vis(250, vector<bool>(1 << n));
  for (int i = 0; i < 250; ++i) {
    fill(vis[i].begin(), vis[i].end(), false);
    vis[i][0] = true;
  }

  for (int j = 0; j <= text.size(); ++j) {
    int cur = j % 250;
    for (int i = 0; i < (1 << n); ++i) {
      if (!vis[cur][i]) continue;
      for (int k = 0; k < n; ++k) {
        if ((~i & (1 << k)) && len[k] + j <= text.size() &&
            ha[k] == gha[j + len[k]] - gha[j] * po[len[k]]) {
          vis[(j + len[k]) % 250][i | (1 << k)] = true;
        }
      }
    }
    ans += vis[cur][(1 << n) - 1];
    fill(vis[cur].begin(), vis[cur].end(), false);
    vis[cur][0] = true;
  }

  cout << ans << endl;
}

int main() {
  while (cin >> n >> m, n) {
    solve();
  }
  return 0;
}
accuracy: 1
time_ms: 2970
memory_kb: 3640
final_rank: 16

code_snippet: #include <algorithm>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

int n, m;
vector<long long> gha(6000);
vector<long long> po(1000);

void solve() {
    vector<long long> ha(n);
    vector<int> len(n);
    for (int i = 0; i < n; ++i) {
        string a;
        cin >> a;
        long long h = 0;
        len[i] = a.size();
        for (char ch : a)
            h = h * 31 + ch;
        ha[i] = h;
    }

    po[0] = 1;
    for (int i = 0; i < 999; ++i)
        po[i + 1] = po[i] * 31;

    int ans = 0;
    string text;
    for (int jjj = 0; jjj < m; ++jjj) {
        string a;
        cin >> a;
        text += a;
    }
    for (int i = 0; i < text.size(); ++i)
        gha[i + 1] = gha[i] * 31 + text[i];

    vector<vector<int>> vis(250, vector<int>(1 << n));

    for (int i = 0; i < 250; ++i)
        vis[i][0] = 1;

    for (int j = 0; j < text.size() + 1; ++j) {
        int cur = j % 250;
        for (int i = 0; i < (1 << n); ++i) {
            if (!vis[cur][i])
                continue;
            for (int k = 0; k < n; ++k) {
                if ((~i & (1 << k)) && len[k] + j <= text.size() &&
                    ha[k] == gha[j + len[k]] - gha[j] * po[len[k]])
                {
                    vis[(j + len[k]) % 250][i | (1 << k)] = 1;
                }
            }
        }
        ans += vis[cur][(1 << n) - 1];
        for (int i = 0; i < (1 << n); ++i)
            vis[cur][i] = 0;
        vis[cur][0] = 1;
    }

    cout << ans << endl;
}

int main() {
    while (cin >> n >> m, n)
        solve();
    return 0;
}
accuracy: 1
time_ms: 2670
memory_kb: 7240
final_rank: 15

code_snippet: #include <iostream>
#include <vector>
#include <string>
#include <algorithm>

void solve(int n, int m) {
  std::vector<std::string> e(n);
  std::string ts;
  int concatenated_len = 0;
  for (int i = 0; i < n; ++i) {
    std::cin >> e[i];
    concatenated_len += e[i].size();
  }
  for (int i = 0; i < m; ++i) {
    std::string t;
    std::cin >> t;
    ts += t;
  }
  std::vector<int> sum_len(1 << n);
  for (int i = 0; i < (1 << n); ++i) {
    for (int j = 0; j < n; ++j) {
      if (((i >> j) & 1) == 0)
        continue;
      sum_len[i] += e[j].size();
    }
  }
  std::vector<std::vector<int>> heads(ts.size());
  std::vector<std::vector<bool>> p(ts.size(), std::vector<bool>(1 << n, false));
  for (int i = 0; i < ts.size(); ++i) p[i][0] = true;
  for (int i = 0; i < ts.size(); ++i) {
    for (int j = 0; j < n; ++j) {
      if (i + e[j].size() > ts.size() || !std::equal(e[j].begin(), e[j].end(), ts.begin() + i))
        continue;
      p[i][1 << j] = true;
      heads[i].push_back(j);
    }
  }
  int ans = 0;
  for (int i = ts.size() - 1; i >= 0; --i) {
    for (int j = 1; j < (1 << n); ++j) {
      if (p[i][j] || i + sum_len[j] > ts.size())
        continue;
      for (int k : heads[i]) {
        if (((j >> k) & 1) == 0)
          continue;
        int i2 = i + e[k].size();
        if (p[i2][j & (~(1 << k))]) {
          p[i][j] = true;
          break;
        }
      }
    }
    if (p[i][(1 << n) - 1])
      ++ans;
  }
  std::cout << ans << "\n";
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.tie(nullptr);
  std::cout.setf(std::ios::fixed);
  std::cout.precision(10);
  for (;;) {
    int n, m;
    std::cin >> n >> m;
    if (n == 0 && m == 0)
      break;
    solve(n, m);
  }
  return 0;
}
accuracy: 1
time_ms: 1480
memory_kb: 6688
final_rank: 1