using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;

namespace Temp
{
    internal class PointInt
    {
        public long X;

        public long Y;

        public PointInt(long x, long y)
        {
            this.X = x;
            this.Y = y;
        }

        public PointInt(PointInt head)
            : this(head.X, head.Y)
        {
        }

        public static PointInt operator +(PointInt a, PointInt b)
        {
            return new PointInt(a.X + b.X, a.Y + b.Y);
        }

        public static PointInt operator -(PointInt a, PointInt b)
        {
            return new PointInt(a.X - b.X, a.Y - b.Y);
        }

        public static PointInt operator *(PointInt a, long k)
        {
            return new PointInt(k * a.X, k * a.Y);
        }

        public static PointInt operator *(long k, PointInt a)
        {
            return new PointInt(k * a.X, k * a.Y);
        }

        public bool IsInsideRectangle(long l, long b, long r, long t)
        {
            return (l <= X) && (X <= r) && (b <= Y) && (Y <= t);
        }

        public bool Equals(PointInt other)
        {
            if (ReferenceEquals(null, other))
            {
                return false;
            }
            if (ReferenceEquals(this, other))
            {
                return true;
            }
            return other.X == this.X && other.Y == this.Y;
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
            {
                return false;
            }
            if (ReferenceEquals(this, obj))
            {
                return true;
            }
            if (obj.GetType() != typeof(PointInt))
            {
                return false;
            }
            return Equals((PointInt)obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                return (this.X.GetHashCode() * 397) ^ this.Y.GetHashCode();
            }
        }
    }

    public class Point2DReal
    {
        public double X;

        public double Y;

        public Point2DReal(double x, double y)
        {
            this.X = x;
            this.Y = y;
        }

        public Point2DReal(Point2DReal head)
            : this(head.X, head.Y)
        {
        }

        public static Point2DReal operator +(Point2DReal a, Point2DReal b)
        {
            return new Point2DReal(a.X + b.X, a.Y + b.Y);
        }

        public static Point2DReal operator -(Point2DReal a, Point2DReal b)
        {
            return new Point2DReal(a.X - b.X, a.Y - b.Y);
        }

        public static Point2DReal operator *(Point2DReal a, double k)
        {
            return new Point2DReal(k * a.X, k * a.Y);
        }

        public static Point2DReal operator *(double k, Point2DReal a)
        {
            return new Point2DReal(k * a.X, k * a.Y);
        }

        public double Dist(Point2DReal p)
        {
            return Math.Sqrt((p.X - X)*(p.X - X) + (p.Y - Y)*(p.Y - Y));
        }

        public bool IsInsideRectangle(double l, double b, double r, double t)
        {
            return (l <= X) && (X <= r) && (b <= Y) && (Y <= t);
        }

        public bool Equals(Point2DReal other)
        {
            if (ReferenceEquals(null, other))
            {
                return false;
            }
            if (ReferenceEquals(this, other))
            {
                return true;
            }
            return other.X == this.X && other.Y == this.Y;
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
            {
                return false;
            }
            if (ReferenceEquals(this, obj))
            {
                return true;
            }
            if (obj.GetType() != typeof(Point2DReal))
            {
                return false;
            }
            return Equals((Point2DReal)obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                return (this.X.GetHashCode() * 397) ^ this.Y.GetHashCode();
            }
        }
    }

    internal class LineInt
    {
        public LineInt(PointInt a, PointInt b)
        {
            A = a.Y - b.Y;
            B = b.X - a.X;
            C = a.X * b.Y - a.Y * b.X;
        }

        public long A, B, C;

        public bool ContainsPoint(PointInt p)
        {
            return A * p.X + B * p.Y + C == 0;
        }

        public int Sign(PointInt p)
        {
            return Math.Sign(A * p.X + B * p.Y + C);
        }
    }

    internal static class Geometry
    {
        public static long VectInt(PointInt a, PointInt b)
        {
            return a.X * b.Y - a.Y * b.X;
        }

        public static long VectInt(PointInt a, PointInt b, PointInt c)
        {
            return (b.X - a.X) * (c.Y - a.Y) - (b.Y - a.Y) * (c.X - a.X);
        }
    }

    internal class MatrixInt
    {
        private readonly long[,] m_Matrix;

        public int Size
        {
            get
            {
                return m_Matrix.GetLength(0);
            }
        }

        public long Mod { get; private set; }

        public MatrixInt(int size, long mod = 0)
        {
            m_Matrix = new long[size,size];
            Mod = mod;
        }

        public MatrixInt(long[,] matrix, long mod = 0)
        {
            this.m_Matrix = matrix;
            Mod = mod;

            for (int i = 0; i < Size; i++)
            {
                for (int j = 0; j < Size; j++)
                {
                    m_Matrix[i, j] %= mod;
                }
            }
        }

        public static MatrixInt GetIdentityMatrix(int size, long mod = 0)
        {
            long[,] matrix = new long[size,size];

            for (int i = 0; i < size; i++)
            {
                matrix[i, i] = 1;
            }

            return new MatrixInt(matrix, mod);
        }

        public long this[int i, int j]
        {
            get
            {
                return m_Matrix[i, j];
            }

            set
            {
                m_Matrix[i, j] = value;
            }
        }

        public static MatrixInt operator +(MatrixInt a, MatrixInt b)
        {
            int n = a.Size;
            long mod = Math.Max(a.Mod, b.Mod);
            long[,] c = new long[n,n];
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    c[i, j] = a[i, j] + b[i, j];
                }
            }

            if (mod > 0)
            {
                for (int i = 0; i < n; i++)
                {
                    for (int j = 0; j < n; j++)
                    {
                        c[i, j] %= mod;
                    }
                }
            }

            return new MatrixInt(c, mod);
        }

        public static MatrixInt operator *(MatrixInt a, MatrixInt b)
        {
            int n = a.Size;
            long mod = Math.Max(a.Mod, b.Mod);

            long[,] c = new long[n,n];

            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    for (int k = 0; k < n; k++)
                    {
                        c[i, j] += a[i, k] * b[k, j];
                        if (mod > 0)
                        {
                            c[i, j] %= mod;
                        }
                    }
                }
            }

            return new MatrixInt(c, mod);
        }
    }

    public static class Permutations
    {
        public static int[] GetRandomPermutation(int n)
        {
            int[] p = new int[n];
            for (int i = 0; i < n; i++)
            {
                p[i] = i;
            }

            Random random = new Random();
            for (int i = n - 1; i > 0; i--)
            {
                int j = random.Next(i + 1);
                int tmp = p[i];
                p[i] = p[j];
                p[j] = tmp;
            }

            return p;
        }

        public static T[] Shuffle<T>(this T[] array)
        {
            int length = array.Length;
            int[] p = GetRandomPermutation(length);
            T[] result = new T[length];
            for (int i = 0; i < length; i++)
            {
                result[i] = array[p[i]];
            }

            return result;
        }

        public static T[] ShuffleSort<T>(this T[] array)
        {
            var result = array.Shuffle();
            Array.Sort(result);
            return result;
        }
    }

    internal static class Algebra
    {
        public static long Phi(long n)
        {
            long result = n;
            for (long i = 2; i * i <= n; i++)
            {
                if (n % i == 0)
                {
                    while (n % i == 0)
                    {
                        n /= i;
                    }

                    result -= result / i;
                }
            }

            if (n > 1)
            {
                result -= result / n;
            }

            return result;
        }

        public static long BinPower(long a, long n, long mod)
        {
            long result = 1;

            while (n > 0)
            {
                if ((n & 1) != 0)
                {
                    result = (result * a) % mod;
                }

                a = (a * a) % mod;
                n >>= 1;
            }

            return result;
        }

        public static MatrixInt MatrixBinPower(MatrixInt a, long n)
        {
            MatrixInt result = MatrixInt.GetIdentityMatrix(a.Size, a.Mod);

            while (n > 0)
            {
                if ((n & 1) != 0)
                {
                    result *= a;
                }

                a *= a;
                n >>= 1;
            }

            return result;
        }

        public static long Gcd(long a, long b)
        {
            return b == 0 ? a : Gcd(b, a % b);
        }

        public static long ExtendedGcd(long a, long b, out long x, out long y)
        {
            if (b == 0)
            {
                x = 1;
                y = 0;
                return a;
            }

            long x1;
            long y1;
            long d = ExtendedGcd(b, a % b, out x1, out y1);
            x = y1;
            y = x1 - (a / b) * y1;
            return d;
        }

        public static long Lcm(long a, long b)
        {
            return (a / Gcd(a, b)) * b;
        }

        public static bool[] GetPrimes(int n)
        {
            n = Math.Max(n, 2);
            bool[] prime = new bool[n + 1];
            for (int i = 2; i <= n; i++)
            {
                prime[i] = true;
            }

            for (int i = 2; i * i <= n; i++)
            {
                if (prime[i])
                {
                    if ((long)i * i <= n)
                    {
                        for (int j = i * i; j <= n; j += i)
                        {
                            prime[j] = false;
                        }
                    }
                }
            }

            return prime;
        }

        public static long GetFibonacciNumber(long n, long mod = 0)
        {
            long[,] matrix = new long[,] { { 0, 1 }, { 1, 1 } };

            MatrixInt result = MatrixBinPower(new MatrixInt(matrix, mod), n);

            return result[1, 1];
        }

        public static long[] GetFibonacciSequence(int n)
        {
            long[] result = new long[n];
            result[0] = result[1] = 1;

            for (int i = 2; i < n; i++)
            {
                result[i] = result[i - 1] + result[i - 2];
            }

            return result;
        }

        public static long GetInverseElement(long a, long mod)
        {
            long x, y;
            long g = ExtendedGcd(a, mod, out x, out y);

            if (g != 1)
            {
                return -1;
            }

            return ((x % mod) + mod) % mod;
        }

        public static long[] GetAllInverseElements(long n, long mod)
        {
            long[] result = new long[n];
            result[1] = 1;
            for (int i = 2; i < n; i++)
            {
                result[i] = (mod - (((mod / i) * result[mod % i]) % mod)) % mod;
            }

            return result;
        }

        public static int GetMinimalPrimeDivisor(int n)
        {
            for (int i = 2; i * i <= n; i++)
            {
                if (n % i == 0)
                {
                    return i;
                }
            }

            return n;
        }

        public static long Sqr(long x)
        {
            return x * x;
        }

        public static int SumOfDigits(long x, long baseMod = 10)
        {
            int res = 0;
            while (x > 0)
            {
                res += (int)(x % baseMod);
                x = x / baseMod;
            }
            return res;
        }
    }

    internal static class Reader
    {
        public static void ReadInt(out int a)
        {
            int[] number = new int[1];
            ReadInt(number);
            a = number[0];
        }

        public static void ReadInt(out int a, out int b)
        {
            int[] numbers = new int[2];
            ReadInt(numbers);
            a = numbers[0];
            b = numbers[1];
        }

        public static void ReadInt(out int int1, out int int2, out int int3)
        {
            int[] numbers = new int[3];
            ReadInt(numbers);
            int1 = numbers[0];
            int2 = numbers[1];
            int3 = numbers[2];
        }

        public static void ReadInt(out int int1, out int int2, out int int3, out int int4)
        {
            int[] numbers = new int[4];
            ReadInt(numbers);
            int1 = numbers[0];
            int2 = numbers[1];
            int3 = numbers[2];
            int4 = numbers[3];
        }

        public static void ReadLong(out long a)
        {
            long[] number = new long[1];
            ReadLong(number);
            a = number[0];
        }

        public static void ReadLong(out long a, out long b)
        {
            long[] numbers = new long[2];
            ReadLong(numbers);
            a = numbers[0];
            b = numbers[1];
        }

        public static void ReadLong(out long int1, out long int2, out long int3)
        {
            long[] numbers = new long[3];
            ReadLong(numbers);
            int1 = numbers[0];
            int2 = numbers[1];
            int3 = numbers[2];
        }

        public static void ReadLong(out long int1, out long int2, out long int3, out long int4)
        {
            long[] numbers = new long[4];
            ReadLong(numbers);
            int1 = numbers[0];
            int2 = numbers[1];
            int3 = numbers[2];
            int4 = numbers[3];
        }

        public static void ReadInt(int[] numbers)
        {
            // ReSharper disable PossibleNullReferenceException
            var list = Console.ReadLine().Split();
            // ReSharper restore PossibleNullReferenceException

            int count = Math.Min(numbers.Length, list.Length);

            for (int i = 0; i < count; i++)
            {
                numbers[i] = int.Parse(list[i]);
            }
        }

        public static int[] ReadDigits()
        {
            // ReSharper disable AssignNullToNotNullAttribute
            return Console.ReadLine().Select(x => int.Parse(x.ToString())).ToArray();
            // ReSharper restore AssignNullToNotNullAttribute
        }

        public static void ReadLong(long[] numbers)
        {
            // ReSharper disable PossibleNullReferenceException
            var list = Console.ReadLine().Split();
            // ReSharper restore PossibleNullReferenceException

            int count = Math.Min(numbers.Length, list.Length);

            for (int i = 0; i < count; i++)
            {
                numbers[i] = long.Parse(list[i]);
            }
        }

        public static void ReadDouble(double[] numbers)
        {
            // ReSharper disable PossibleNullReferenceException
            var list = Console.ReadLine().Split();
            // ReSharper restore PossibleNullReferenceException

            int count = Math.Min(numbers.Length, list.Length);

            for (int i = 0; i < count; i++)
            {
                numbers[i] = double.Parse(list[i]);
            }
        }

        public static void ReadDouble(out double a, out double b)
        {
            double[] numbers = new double[2];
            ReadDouble(numbers);
            a = numbers[0];
            b = numbers[1];
        }

        public static void ReadDouble(out double int1, out double int2, out double int3)
        {
            double[] numbers = new double[3];
            ReadDouble(numbers);
            int1 = numbers[0];
            int2 = numbers[1];
            int3 = numbers[2];
        }

        public static string ReadLine()
        {
            return Console.ReadLine();
        }
    }

    public interface IGraph
    {
        int Vertices { get; set; }

        IList<int> this[int i] { get; }

        void AddEdge(int u, int v);

        void AddOrientedEdge(int u, int v);
    }

    public class Graph : IGraph
    {
        private readonly List<int>[] m_Edges;

        public int Vertices { get; set; }

        public IList<int> this[int i]
        {
            get
            {
                return this.m_Edges[i];
            }
        }

        public Graph(int vertices)
        {
            this.Vertices = vertices;

            this.m_Edges = new List<int>[vertices];

            for (int i = 0; i < vertices; i++)
            {
                this.m_Edges[i] = new List<int>();
            }
        }

        public void AddEdge(int u, int v)
        {
            this.AddOrientedEdge(u, v);
            this.AddOrientedEdge(v, u);
        }

        public void AddOrientedEdge(int first, int second)
        {
            this.m_Edges[first].Add(second);
        }

        public int[] Bfs(int start)
        {
            int[] d = new int[Vertices];
            for (int i = 0; i < Vertices; i++)
            {
                d[i] = -1;
            }

            Queue<int> queue = new Queue<int>();
            queue.Enqueue(start);
            d[start] = 0;

            while (queue.Count > 0)
            {
                int v = queue.Dequeue();
                foreach (int t in this.m_Edges[v].Where(t => d[t] == -1))
                {
                    queue.Enqueue(t);
                    d[t] = d[v] + 1;
                }
            }

            return d;
        }
    }

    internal class SimpleSumTable
    {
        private readonly int[,] m_Sum;

        public SimpleSumTable(int n, int m, int[,] table)
        {
            m_Sum = new int[n + 1,m + 1];

            for (int i = 1; i < n + 1; i++)
            {
                for (int j = 1; j < m + 1; j++)
                {
                    m_Sum[i, j] = m_Sum[i, j - 1] + m_Sum[i - 1, j] - m_Sum[i - 1, j - 1] + table[i - 1, j - 1];
                }
            }
        }

        public int GetSum(int l, int b, int r, int t)
        {
            return m_Sum[r + 1, t + 1] - m_Sum[r + 1, b] - m_Sum[l, t + 1] + m_Sum[l, b];
        }
    }

    internal class SegmentTreeSimpleInt<T>
    {
        public int Size { get; private set; }

        private readonly T[] m_Tree;

        private readonly Func<T, T, T> m_Operation;

        private readonly T m_Null;

        public SegmentTreeSimpleInt(int size, Func<T, T, T> operation, T nullElement, IList<T> array = null)
        {
            this.Size = size;
            this.m_Operation = operation;
            this.m_Null = nullElement;

            m_Tree = new T[4 * size];
            if (array != null)
            {
                this.Build(array, 1, 0, size - 1);
            }
        }

        private void Build(IList<T> array, int v, int tl, int tr)
        {
            if (tl == tr)
            {
                m_Tree[v] = array[tl];
            }
            else
            {
                int tm = (tl + tr) / 2;
                this.Build(array, 2 * v, tl, tm);
                this.Build(array, 2 * v + 1, tm + 1, tr);
                this.CalculateNode(v);
            }
        }

        public T GetSum(int l, int r)
        {
            return GetSum(1, 0, Size - 1, l, r);
        }

        private T GetSum(int v, int tl, int tr, int l, int r)
        {
            if (l > r)
            {
                return m_Null;
            }

            if (l == tl && r == tr)
            {
                return m_Tree[v];
            }

            int tm = (tl + tr) / 2;

            return this.m_Operation(
                GetSum(2 * v, tl, tm, l, Math.Min(r, tm)), GetSum(2 * v + 1, tm + 1, tr, Math.Max(l, tm + 1), r));
        }

        public void Update(int pos, T newValue)
        {
            Update(1, 0, Size - 1, pos, newValue);
        }

        private void Update(int v, int tl, int tr, int pos, T newValue)
        {
            if (tl == tr)
            {
                m_Tree[v] = newValue;
            }
            else
            {
                int tm = (tl + tr) / 2;
                if (pos <= tm)
                {
                    Update(2 * v, tl, tm, pos, newValue);
                }
                else
                {
                    Update(2 * v + 1, tm + 1, tr, pos, newValue);
                }
                this.CalculateNode(v);
            }
        }

        private void CalculateNode(int v)
        {
            m_Tree[v] = this.m_Operation(m_Tree[2 * v], m_Tree[2 * v + 1]);
        }
    }

    internal class Pair<TFirst, TSecond>
    {
        public Pair(TFirst first, TSecond second)
        {
            this.First = first;
            this.Second = second;
        }

        public TFirst First { set; get; }

        public TSecond Second { set; get; }

        protected bool Equals(Pair<TFirst, TSecond> other)
        {
            return EqualityComparer<TFirst>.Default.Equals(this.First, other.First) && EqualityComparer<TSecond>.Default.Equals(this.Second, other.Second);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
            {
                return false;
            }
            if (ReferenceEquals(this, obj))
            {
                return true;
            }
            if (obj.GetType() != this.GetType())
            {
                return false;
            }
            return Equals((Pair<TFirst, TSecond>)obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                return (EqualityComparer<TFirst>.Default.GetHashCode(this.First) * 397) ^ EqualityComparer<TSecond>.Default.GetHashCode(this.Second);
            }
        }
    }

    internal class FenwickTreeInt64
    {
        public FenwickTreeInt64(int size)
        {
            this.m_Size = size;
            m_Tree = new long[size];
        }

        public FenwickTreeInt64(int size, IList<long> tree)
            : this(size)
        {
            for (int i = 0; i < size; i++)
            {
                Inc(i, tree[i]);
            }
        }

        public long Sum(int r)
        {
            long res = 0;
            for (; r >= 0; r = (r & (r + 1)) - 1)
            {
                res += m_Tree[r];
            }
            return res;
        }

        public long Sum(int l, int r)
        {
            return Sum(r) - Sum(l - 1);
        }

        public void Inc(int i, long x)
        {
            for (; i < m_Size; i = i | (i + 1))
            {
                m_Tree[i] += x;
            }
        }

        public void Set(int i, long x)
        {
            Inc(i, x - Sum(i, i));
        }

        private readonly int m_Size;

        private readonly long[] m_Tree;
    }

    internal class AccumulativeDictionary<TKey> : Dictionary<TKey, int>
    {
        public new void Add(TKey key, int value = 1)
        {
            if (this.ContainsKey(key))
            {
                base[key] += value;
            }
            else
            {
                base.Add(key, value);
            }
        }

        public new int this[TKey key]
        {
            get
            {
                return this.ContainsKey(key) ? base[key] : 0;
            }
            set
            {
                this.Add(key, value);
            }
        }
    }

    public class PriorityQueue<T>
    {
        public PriorityQueue(Comparison<T> comparison = null)
        {
            if (comparison == null)
            {
                if (typeof(T).GetInterfaces().Any(i => i == typeof(IComparable<T>)))
                {
                    m_Comparison = (a, b) => ((IComparable<T>)a).CompareTo(b);
                }
                else
                {
                    throw new ApplicationException("Add comparer");
                }
            }
            else
            {
                m_Comparison = comparison;
            }
        }

        public int Count { get; private set; }

        public void Enqueue(T item)
        {
            m_List.Add(item);
            m_Indexes.Add(item, this.Count);
            this.Count++;
            Up(this.Count);
        }

        public T Peek()
        {
            return m_List[0];
        }

        public T Dequeue()
        {
            if (this.Count > 0)
            {
                var result = m_List[0];

                Swap(0, this.Count - 1);
                m_Indexes.Remove(m_List[this.Count - 1]);
                m_List.RemoveAt(this.Count - 1);
                this.Count--;
                this.Down(1);

                return result;
            }
            throw new ApplicationException("Couldn't get element from empty queue");
        }

        public void Update(T item)
        {
            int index = m_Indexes[item];
            this.Up(index + 1);
        }

        private readonly List<T> m_List = new List<T>();

        private readonly Dictionary<T, int> m_Indexes = new Dictionary<T, int>();

        private readonly Comparison<T> m_Comparison;

        private void Up(int index)
        {
            while (index > 1 && m_Comparison.Invoke(m_List[index - 1], m_List[index / 2 - 1]) > 0)
            {
                this.Swap(index - 1, index / 2 - 1);

                index = index / 2;
            }
        }

        private void Down(int index)
        {
            while (2 * index <= this.Count && m_Comparison.Invoke(m_List[index - 1], m_List[2 * index - 1]) < 0
                   || 2 * index + 1 <= this.Count && m_Comparison.Invoke(m_List[index - 1], m_List[2 * index]) < 0)
            {
                if (2 * index + 1 > this.Count || m_Comparison.Invoke(m_List[2 * index - 1], m_List[2 * index]) > 0)
                {
                    this.Swap(index - 1, 2 * index - 1);
                    index = 2 * index;
                }
                else
                {
                    this.Swap(index - 1, 2 * index);
                    index = 2 * index + 1;
                }
            }
        }

        private void Swap(int i, int j)
        {
            var tmp = m_List[i];
            m_List[i] = m_List[j];
            m_List[j] = tmp;

            m_Indexes[m_List[i]] = i;
            m_Indexes[m_List[j]] = j;
        }
    }

    public class DisjointSetUnion<T>
    {
        public DisjointSetUnion()
        {
            m_Parent = new Dictionary<T, T>();
            m_Rank = new Dictionary<T, int>();
        }

        public DisjointSetUnion(DisjointSetUnion<T> set)
        {
            m_Parent = new Dictionary<T, T>(set.m_Parent);
            m_Rank = new Dictionary<T, int>(set.m_Rank);
        }

        private readonly Dictionary<T, T> m_Parent;
        private readonly Dictionary<T, int> m_Rank;

        public int GetRank(T x)
        {
            return m_Rank[x];
        }

        public void MakeSet(T x)
        {
            m_Parent[x] = x;
            this.m_Rank[x] = 0;
        }

        public void UnionSets(T x, T y)
        {
            x = this.FindSet(x);
            y = this.FindSet(y);
            if (!x.Equals(y))
            {
                if (m_Rank[x] < m_Rank[y])
                {
                    T t = x;
                    x = y;
                    y = t;
                }
                m_Parent[y] = x;
                if (m_Rank[x] == m_Rank[y])
                {
                    m_Rank[x]++;
                }
            }
        }

        public T FindSet(T x)
        {
            if (x.Equals(m_Parent[x]))
            {
                return x;
            }
            return m_Parent[x] = this.FindSet(m_Parent[x]);
        }
    }

    internal class HamiltonianPathFinder
    {
        public static void Run()
        {
            int n, m;
            Reader.ReadInt(out n, out m);
            List<int>[] a = new List<int>[n];
            for (int i = 0; i < n; i++)
            {
                a[i] = new List<int>();
            }
            for (int i = 0; i < m; i++)
            {
                int x, y;
                Reader.ReadInt(out x, out y);
                a[x].Add(y);
                a[y].Add(x);
            }

            var rnd = new Random();

            bool[] v = new bool[n];
            int[] p = new int[n];
            for (int i = 0; i < n; i++)
            {
                p[i] = -1;
            }
            int first = rnd.Next(n);
            int cur = first;
            v[cur] = true;

            int count = 1;

            while (true)
            {
                var unb = a[cur].Where(u => !v[u]).ToList();
                int d = unb.Count;
                if (d > 0)
                {
                    int next = unb[rnd.Next(d)];
                    v[next] = true;
                    p[cur] = next;
                    cur = next;
                    count++;
                }
                else
                {
                    if (count  == n && a[cur].Contains(first))
                    {
                        p[cur] = first;
                        break;
                    }

                    d = a[cur].Count;
                    int pivot;
                    do
                    {
                        pivot = a[cur][rnd.Next(d)];
                    }
                    while (p[pivot] == cur);

                    int next = p[pivot];

                    int x = next;
                    int y = -1;
                    while (true)
                    {
                        int tmp = p[x];
                        p[x] = y;
                        y = x;
                        x = tmp;
                        if (y == cur)
                        {
                            break;
                        }
                    }
                    p[pivot] = cur;
                    cur = next;
                }
            }

            cur = first;
            do
            {
                Console.Write("{0} ", cur);
                cur = p[cur];
            }
            while (cur != first);
        }

        public static void WriteTest(int n)
        {
            Console.WriteLine("{0} {1}", 2 * n, 2 * (n - 1) + n);
            for (int i = 0; i < n - 1; i++)
            {
                Console.WriteLine("{0} {1}", 2 * i, 2 * i + 2);
                Console.WriteLine("{0} {1}", 2 * i + 1, 2 * i + 3);
                //Console.WriteLine("{0} {1}", 2 * i + 1, 2 * i + 2);
                //Console.WriteLine("{0} {1}", 2 * i, 2 * i + 3);
            }
            for (int i = 0; i < n; i++)
            {
                Console.WriteLine("{0} {1}", 2 * i, 2 * i + 1);
            }
        }
    }

    internal class Backtrack<T> where T : class
    {
        public Backtrack(Func<T, IEnumerable<T>> generator)
        {
            this.m_Generator = generator;
        }

        public Dictionary<T, T> Generate(T startState)
        {
            var result = new Dictionary<T, T>();
            result.Add(startState, null);

            var queue = new Queue<T>();
            queue.Enqueue(startState);

            while (queue.Count > 0)
            {
                var current = queue.Dequeue();
                var next = m_Generator(current);
                foreach (var state in next)
                {
                    if (!result.ContainsKey(state))
                    {
                        result[state] = current;
                        queue.Enqueue(state);
                    }
                }
            }

            return result;
        }

        private Func<T, IEnumerable<T>> m_Generator;
    }

    internal class Program
    {
        private static StreamReader m_InputStream;

        private static StreamWriter m_OutStream;

        private static void OpenFiles()
        {
            m_InputStream = new StreamReader("input.txt"); //File.OpenText("input.txt");
            Console.SetIn(m_InputStream);

            m_OutStream = new StreamWriter("output.txt"); //File.CreateText("output.txt");
            Console.SetOut(m_OutStream);
        }

        private static void CloseFiles()
        {
            m_OutStream.Flush();

            m_InputStream.Dispose();
            m_OutStream.Dispose();
        }

        private static void Main()
        {
            //OpenFiles();

            new Solution().Solve();

           // CloseFiles();
        }
    }

    internal class Solution
    {
        public void Solve()
        {
            long p1 = 1000000007;
            long p2 = 1000000009;

            var s = Console.ReadLine();
            var e = Console.ReadLine();
            var isBad = new bool[26];
            for (int i = 0; i < 26; i++)
            {
                isBad[i] = e[i] == '0';
            }
            int k;
            Reader.ReadInt(out k);

            int ans = 0;
            int n = s.Length;
            var dict = new Dictionary<Hp, bool>();
            for (int i = 0; i < n; i++)
            {
                int cur = 0;
                long curM1 = 0;
                long curM2 = 0;
                for (int j = i; j < n; j++)
                {
                    int num = s[j] - 'a';
                    curM1 = (199967 * curM1 + num + 1) % p1;
                    curM2 = (199999 * curM2 + num + 1) % p2;
                    if (isBad[num])
                    {
                        cur++;
                    }
                    if (cur <= k)
                    {
                        var hp = new Hp(curM1, curM2);
                        if (!dict.ContainsKey(hp))
                        {
                            dict.Add(hp, true);
                            ans++;
                        }
                    }
                }
            }

            Console.WriteLine(ans);
        }

        public class Hp
        {
            public Hp(long m1, long m2)
            {
                this.M1 = m1;
                this.M2 = m2;
            }

            protected bool Equals(Hp other)
            {
                return this.M1 == other.M1 && this.M2 == other.M2;
            }

            public override bool Equals(object obj)
            {
                if (ReferenceEquals(null, obj))
                {
                    return false;
                }
                if (ReferenceEquals(this, obj))
                {
                    return true;
                }
                if (obj.GetType() != this.GetType())
                {
                    return false;
                }
                return Equals((Hp)obj);
            }

            public override int GetHashCode()
            {
                unchecked
                {
                    return (this.M1.GetHashCode() * 397) ^ this.M2.GetHashCode();
                }
            }

            public readonly long M1;

            public readonly long M2;
        }
    }
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace Codeforces._271
{
    public class D
    {
        public static void Main()
        {
            StreamWriter sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
            new D().Solve(Console.In, sw);
            sw.Flush();
        }

        public void Solve(TextReader tr, TextWriter tw)
        {
            var s = tr.ReadLine();
            var g = tr.ReadLine();
            var k = int.Parse(tr.ReadLine());

            var res = Solve(s, g, k);

            tw.WriteLine(res);
        }

        public int Solve(string s, string good, int k)
        {
            var set = new HashSet<string>();
            for (int i = 0; i < s.Length; ++i)
            {
                var bad = 0;
                var sb = new StringBuilder();
                for (int j = 0; i + j < s.Length; ++j)
                {
                    var c = s[i + j];
                    if (good[c - 'a'] == '0')
                    {
                        ++bad;
                    }
                    if (bad > k)
                    {
                        break;
                    }
                    sb.Append(c);
                    set.Add(sb.ToString());
                }
            }
            return set.Count;
        }
    }
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Codeforces._271
{
    class Trie
    {
        private readonly Node root;

        public Trie()
        {
            root = new Node('^', 0, null);
        }

        internal int Count
        {
            get
            {
                return root.Count;
            }
        }

        public Node Prefix(string s)
        {
            var currentNode = root;
            var result = currentNode;

            foreach (var c in s)
            {
                currentNode = currentNode.FindChildNode(c);
                if (currentNode == null)
                    break;
                result = currentNode;
            }

            return result;
        }

        public class Node
        {
            public char Value { get; set; }
            public List<Node> Children { get; set; }
            public Node Parent { get; set; }
            public int Depth { get; set; }
            public int Count
            {
                get
                {
                    var c = Value != '^' ? 1 : 0;
                    foreach (var node in Children)
                    {
                        c += node.Count;
                    }
                    return c;
                }
            }

            public Node(char value, int depth, Node parent)
            {
                Value = value;
                Children = new List<Node>();
                Depth = depth;
                Parent = parent;
            }

            public Node FindChildNode(char c)
            {
                foreach (var child in Children)
                    if (child.Value == c)
                        return child;

                return null;
            }

            internal Node Append(char c)
            {
                var child = FindChildNode(c);
                if (child != null)
                {
                    return child;
                }
                child = new Node(c, Depth + 1, this);
                Children.Add(child);
                return child;
            }
        }
    }

    public class D
    {
        public static void Main()
        {
            StreamWriter sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
            new D().Solve(Console.In, sw);
            sw.Flush();
        }

        public void Solve(TextReader tr, TextWriter tw)
        {
            var s = tr.ReadLine();
            var g = tr.ReadLine();
            var k = int.Parse(tr.ReadLine());

            var res = Solve(s, g, k);

            tw.WriteLine(res);
        }

        public int Solve(string s, string good, int k)
        {
            var set = new Trie.Node('^', 0, null);
            for (int i = 0; i < s.Length; ++i)
            {
                var bad = 0;
                var sb = new StringBuilder();
                var node = set;
                for (int j = 0; i + j < s.Length; ++j)
                {
                    var c = s[i + j];
                    if (good[c - 'a'] == '0')
                    {
                        ++bad;
                    }
                    if (bad > k)
                    {
                        break;
                    }
                    sb.Append(c);
                    node = node.Append(c);
                }
            }
            return set.Count;
        }
    }
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Codeforces._271
{
    class Trie
    {
        private readonly Node root;

        public Trie()
        {
            root = new Node('^', 0, null);
        }

        internal int Count
        {
            get
            {
                return root.Count;
            }
        }

        public Node Prefix(string s)
        {
            var currentNode = root;
            var result = currentNode;

            foreach (var c in s)
            {
                currentNode = currentNode.FindChildNode(c);
                if (currentNode == null)
                    break;
                result = currentNode;
            }

            return result;
        }
        internal void Add(string s)
        {
            var commonPrefix = Prefix(s);
            var current = commonPrefix;

            for (var i = current.Depth; i < s.Length; i++)
            {
                var newNode = new Node(s[i], current.Depth + 1, current);
                current.Children.Add(newNode);
                current = newNode;
            }
        }

        public class Node
        {
            public char Value { get; set; }
            public List<Node> Children { get; set; }
            public Node Parent { get; set; }
            public int Depth { get; set; }
            public int Count
            {
                get
                {
                    var c = Value != '^' ? 1 : 0;
                    foreach (var node in Children)
                    {
                        c += node.Count;
                    }
                    return c;
                }
            }

            public Node(char value, int depth, Node parent)
            {
                Value = value;
                Children = new List<Node>();
                Depth = depth;
                Parent = parent;
            }

            public Node FindChildNode(char c)
            {
                foreach (var child in Children)
                    if (child.Value == c)
                        return child;

                return null;
            }
        }
    }

    public class D
    {
        public static void Main()
        {
            StreamWriter sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
            new D().Solve(Console.In, sw);
            sw.Flush();
        }

        public void Solve(TextReader tr, TextWriter tw)
        {
            var s = tr.ReadLine();
            var g = tr.ReadLine();
            var k = int.Parse(tr.ReadLine());

            var res = Solve(s, g, k);

            tw.WriteLine(res);
        }

        public int Solve(string s, string good, int k)
        {
            var set = new Trie();
            for (int i = 0; i < s.Length; ++i)
            {
                var bad = 0;
                var sb = new StringBuilder();
                for (int j = 0; i + j < s.Length; ++j)
                {
                    var c = s[i + j];
                    if (good[c - 'a'] == '0')
                    {
                        ++bad;
                    }
                    if (bad > k)
                    {
                        break;
                    }
                    sb.Append(c);
                    set.Add(sb.ToString());
                }
            }
            return set.Count;
        }
    }
}


using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.IO;
using System.Globalization;
using System.Collections;

namespace Task
{
    internal class Program
    {
        private void Solve()
        {
            string s = io.NextLine();
            string bin = io.NextLine();
            int k = io.NextInt();

            long p = 1091632000284821L;
            HashSet<long>[] sets = new HashSet<long>[s.Length];
            for (int i = 0; i < sets.Length; i++)
                sets[i] = new HashSet<long>();

            for (int i = 0; i < s.Length; i++)
            {
                int cnt = 0;
                long h = 0;
                for (int j = i; j < s.Length; j++)
                {
                    if (bin[s[j] - 'a'] == '0')
                        cnt++;
                    if (cnt > k)
                        break;
                    h = h * 29 + s[j] - 'a' + 1;
                    h %= p;
                    sets[j - i].Add(h);
                }
            }
            int ans = 0;
            foreach (var set in sets)
                ans += set.Count;
            io.Print(ans);
        }

        #region Program

        private readonly MyIo io;

        public Program(MyIo io)
        {
            this.io = io;
        }

        public static void Main(string[] args)
        {
            using (MyIo io = new MyIo())
            {
                new Program(io).Solve();
            }
        }

        #endregion
    }

    #region MyIo

    internal class MyIo : IDisposable
    {
        private readonly TextReader inputStream;
        private readonly TextWriter outputStream = Console.Out;

        private string[] tokens;
        private int pointer;

        public MyIo()
#if  LOCAL_TEST
            : this(new StreamReader("..\\..\\input.txt"))
#else
            : this(System.Console.In)
#endif
        {

        }

        public MyIo(TextReader inputStream)
        {
            this.inputStream = inputStream;
        }

        public string NextLine()
        {
            try
            {
                return inputStream.ReadLine();
            }
            catch (IOException)
            {
                return null;
            }
        }

        public string NextString()
        {
            try
            {
                while (tokens == null || pointer >= tokens.Length)
                {
                    tokens = NextLine().Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
                    pointer = 0;
                }
                return tokens[pointer++];
            }
            catch (IOException)
            {
                return null;
            }
        }

        public int NextInt()
        {
            return Next<int>();
        }

        public long NextLong()
        {
            return Next<long>();
        }

        public T Next<T>()
        {
            return (T)Convert.ChangeType(NextString(), typeof(T));
        }

        public IEnumerable<T> NextSeq<T>(int n)
        {
            for (int i = 0; i < n; i++)
                yield return Next<T>();
        }

        public void Print(string format, params object[] args)
        {
            outputStream.Write(string.Format(CultureInfo.InvariantCulture, format, args));
        }

        public void PrintLine(string format, params object[] args)
        {
            Print(format, args);

            outputStream.WriteLine();
        }

        public void Print(bool o)
        {
            Print(o ? "YES" : "NO");
        }

        public void PrintLine(bool o)
        {
            PrintLine(o ? "YES" : "NO");
        }

        public void Print<T>(T o)
        {
            outputStream.Write(o);
        }

        public void PrintLine<T>(T o)
        {
            outputStream.WriteLine(o);
        }

        public void Close()
        {
            inputStream.Close();
            outputStream.Close();
        }

        void IDisposable.Dispose()
        {
            Close();

#if  LOCAL_TEST
            Console.ReadLine();
#endif
        }
    }

    #endregion
}


#![allow(unused_imports)]
#![allow(dead_code)]
use datastructure::*;
use grapth::*;
use input_scanner::*;
use math::*;
use string_algorithm::*;
use util::*;

use std::cmp;
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};

fn main() {
    let mut scan = Scanner::new();
    let s = scan.next_chars();
    let bad = scan.next_chars();
    let k: i32 = scan.next();
    let mrh = MultiRollingHash::new(&s, &[17, 1000000007]);
    let mut set: HashSet<u64> = HashSet::new();

    for len in 1..s.len() + 1 {
        let mut cnt: i32 = 0;
        for i in 0..len - 1 {
            if bad[s[i] as usize - 'a' as usize] == '0' {
                cnt += 1;
            }
        }
        for i in 0..s.len() + 1 - len {
            if bad[s[i + len - 1] as usize - 'a' as usize] == '0' {
                cnt += 1;
            }
            if cnt <= k {
                set.insert(mrh.hash(i, i + len));
            }
            if bad[s[i] as usize - 'a' as usize] == '0' {
                cnt -= 1;
            }
        }
    }
    println!("{}", set.len());
}

mod datastructure {}
mod grapth {}
mod math {}
mod util {}
mod string_algorithm {
    pub struct RollingHash {
        hash: Vec<u64>,
        inv: Vec<u64>,
    }

    impl RollingHash {
        fn inverse(mut x: u64) -> u64 {
            let mut ret: u64 = 1;
            for _i in 0..64 {
                ret = ret.wrapping_mul(x);
                x = x.wrapping_mul(x);
            }
            ret
        }
        pub fn new(text: &[char], base: u64) -> Self {
            assert!(base % 2 == 1);
            let inv = RollingHash::inverse(base);
            let mut b = base;
            let mut h_i = 0u64;
            let mut inv_i = 1u64;
            let mut hash: Vec<u64> = Vec::with_capacity(text.len() + 1);
            let mut invs: Vec<u64> = Vec::with_capacity(text.len() + 1);
            hash.push(h_i);
            invs.push(inv_i);
            for ch in text {
                b = b.wrapping_mul(base);
                h_i = b.wrapping_mul(*ch as u64).wrapping_add(h_i);
                hash.push(h_i);
                inv_i = inv_i.wrapping_mul(inv);
                invs.push(inv_i);
            }
            RollingHash {
                hash: hash,
                inv: invs,
            }
        }
        // [s, e)
        pub fn hash(&self, s: usize, e: usize) -> u64 {
            (self.hash[e].wrapping_sub(self.hash[s])).wrapping_mul(self.inv[s])
        }
    }

    pub struct MultiRollingHash {
        rhs: Vec<RollingHash>,
    }

    impl MultiRollingHash {
        pub fn new(text: &[char], bases: &[u64]) -> Self {
            let mut rhs = Vec::with_capacity(bases.len());
            for b in bases {
                rhs.push(RollingHash::new(text, *b));
            }
            MultiRollingHash { rhs: rhs }
        }
        pub fn hash(&self, s: usize, e: usize) -> u64 {
            self.rhs.iter().fold(0, |sum, x| sum ^ x.hash(s, e))
        }
    }
}
mod input_scanner {
    pub struct Scanner {
        line: Vec<String>,
        idx: usize,
    }

    impl Scanner {
        pub fn new() -> Self {
            let mut buffer = String::new();
            std::io::Read::read_to_string(&mut std::io::stdin(), &mut buffer).unwrap();
            Scanner {
                line: buffer
                    .trim()
                    .split_ascii_whitespace()
                    .collect::<Vec<&str>>()
                    .iter()
                    .map(|&s| String::from(s))
                    .collect(),
                idx: 0,
            }
        }
        pub fn next<T>(&mut self) -> T
        where
            T: std::str::FromStr,
            T::Err: std::fmt::Debug,
        {
            let ret: T = self.line[self.idx].parse::<T>().unwrap();
            self.idx += 1;
            ret
        }
        pub fn next_vec<T>(&mut self, n: usize) -> Vec<T>
        where
            T: std::str::FromStr,
            T::Err: std::fmt::Debug,
        {
            let mut v: Vec<T> = Vec::with_capacity(n);
            for _i in 0..n {
                v.push(self.next());
            }
            v
        }
        pub fn next_chars(&mut self) -> Vec<char> {
            let s: String = self.next();
            s.chars().collect::<Vec<char>>()
        }
    }
}


#![allow(unused_imports)]
#![allow(dead_code)]
use datastructure::*;
use grapth::*;
use input_scanner::*;
use math::*;
use string_algorithm::*;
use util::*;

use std::cmp;
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};

fn main() {
    let mut scan = Scanner::new();
    let s = scan.next_chars();
    let bad = scan.next_chars();
    let k: i32 = scan.next();
    let rh = RollingHash::new(&s);
    let mut set: HashSet<u64> = HashSet::new();

    for len in 1..s.len() + 1 {
        let mut cnt: i32 = 0;
        for i in 0..len - 1 {
            if bad[s[i] as usize - 'a' as usize] == '0' {
                cnt += 1;
            }
        }
        for i in 0..s.len() + 1 - len {
            if bad[s[i + len - 1] as usize - 'a' as usize] == '0' {
                cnt += 1;
            }
            if cnt <= k {
                set.insert(rh.hash(i, i+len));
            }
            if bad[s[i] as usize - 'a' as usize] == '0' {
                cnt -= 1;
            }
        }
    }
    println!("{}", set.len());
}

mod datastructure {}
mod grapth {}
mod math {}
mod util {}
mod string_algorithm {
    pub struct RollingHash {
        hash: Vec<u64>,
        inv: Vec<u64>,
    }

    impl RollingHash {
        fn inverse(mut x: u64) -> u64 {
            let mut ret: u64 = 1;
            for _i in 0..64 {
                ret = ret.wrapping_mul(x);
                x = x.wrapping_mul(x);
            }
            ret
        }
        pub fn new(text: &[char]) -> Self {
            let base = 17u64;
            let inv = RollingHash::inverse(base);
            let mut b = base;
            let mut h_i = 0u64;
            let mut inv_i = 1u64;
            let mut hash: Vec<u64> = Vec::with_capacity(text.len() + 1);
            let mut invs: Vec<u64> = Vec::with_capacity(text.len() + 1);
            hash.push(h_i);
            invs.push(inv_i);
            for ch in text {
                b = b.wrapping_mul(base);
                h_i = b.wrapping_mul(*ch as u64).wrapping_add(h_i);
                hash.push(h_i);
                inv_i = inv_i.wrapping_mul(inv);
                invs.push(inv_i);
            }
            RollingHash {
                hash: hash,
                inv: invs,
            }
        }
        // [s, e)
        pub fn hash(&self, s: usize, e: usize) -> u64 {
            (self.hash[e].wrapping_sub(self.hash[s])).wrapping_mul(self.inv[s])
        }
    }
}
mod input_scanner {
    pub struct Scanner {
        line: Vec<String>,
        idx: usize,
    }

    impl Scanner {
        pub fn new() -> Self {
            let mut buffer = String::new();
            std::io::Read::read_to_string(&mut std::io::stdin(), &mut buffer).unwrap();
            Scanner {
                line: buffer
                    .trim()
                    .split_ascii_whitespace()
                    .collect::<Vec<&str>>()
                    .iter()
                    .map(|&s| String::from(s))
                    .collect(),
                idx: 0,
            }
        }
        pub fn next<T>(&mut self) -> T
        where
            T: std::str::FromStr,
            T::Err: std::fmt::Debug,
        {
            let ret: T = self.line[self.idx].parse::<T>().unwrap();
            self.idx += 1;
            ret
        }
        pub fn next_vec<T>(&mut self, n: usize) -> Vec<T>
        where
            T: std::str::FromStr,
            T::Err: std::fmt::Debug,
        {
            let mut v: Vec<T> = Vec::with_capacity(n);
            for _i in 0..n {
                v.push(self.next());
            }
            v
        }
        pub fn next_chars(&mut self) -> Vec<char> {
            let s: String = self.next();
            s.chars().collect::<Vec<char>>()
        }
    }
}


#![allow(unused_imports)]
#![allow(dead_code)]
use datastructure::*;
use grapth::*;
use input_scanner::*;
use math::*;
use string_algorithm::*;
use util::*;

use std::cmp;
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};

fn main() {
    let mut scan = Scanner::new();
    let s = scan.next_chars();
    let bad = scan.next_chars();
    let k: i32 = scan.next();
    let mrh = MultiRollingHash::new(&s, &[17, 1000000007]);
    let mut set: HashSet<u64> = HashSet::new();

    for len in 1..s.len() + 1 {
        let mut cnt: i32 = 0;
        for i in 0..len - 1 {
            if bad[s[i] as usize - 'a' as usize] == b'0' {
                cnt += 1;
            }
        }
        for i in 0..s.len() + 1 - len {
            if bad[s[i + len - 1] as usize - 'a' as usize] == b'0' {
                cnt += 1;
            }
            if cnt <= k {
                set.insert(mrh.hash(i, i + len));
            }
            if bad[s[i] as usize - 'a' as usize] == b'0' {
                cnt -= 1;
            }
        }
    }
    println!("{}", set.len());
}

mod datastructure {}
mod grapth {}
mod math {}
mod util {}
mod string_algorithm {
    pub struct RollingHash {
        hash: Vec<u64>,
        inv: Vec<u64>,
    }

    impl RollingHash {
        fn inverse(mut x: u64) -> u64 {
            let mut ret: u64 = 1;
            for _i in 0..64 {
                ret = ret.wrapping_mul(x);
                x = x.wrapping_mul(x);
            }
            ret
        }
        pub fn new<T>(text: &[T], base: u64) -> Self
        where
            T: Copy,
            u64: std::convert::From<T>,
        {
            assert!(base % 2 == 1);
            let inv = RollingHash::inverse(base);
            let mut b = base;
            let mut h_i = 0u64;
            let mut inv_i = 1u64;
            let mut hash: Vec<u64> = Vec::with_capacity(text.len() + 1);
            let mut invs: Vec<u64> = Vec::with_capacity(text.len() + 1);
            hash.push(h_i);
            invs.push(inv_i);
            for ch in text {
                b = b.wrapping_mul(base);
                h_i = b.wrapping_mul(u64::from(*ch)).wrapping_add(h_i);
                hash.push(h_i);
                inv_i = inv_i.wrapping_mul(inv);
                invs.push(inv_i);
            }
            RollingHash {
                hash: hash,
                inv: invs,
            }
        }
        // [s, e)
        pub fn hash(&self, s: usize, e: usize) -> u64 {
            (self.hash[e].wrapping_sub(self.hash[s])).wrapping_mul(self.inv[s])
        }
    }

    pub struct MultiRollingHash {
        rhs: Vec<RollingHash>,
    }

    impl MultiRollingHash {
        pub fn new<T>(text: &[T], bases: &[u64]) -> Self
        where
            T: Copy,
            u64: std::convert::From<T>,
        {
            let mut rhs = Vec::with_capacity(bases.len());
            for b in bases {
                rhs.push(RollingHash::new(text, *b));
            }
            MultiRollingHash { rhs: rhs }
        }
        pub fn hash(&self, s: usize, e: usize) -> u64 {
            self.rhs.iter().fold(0, |sum, x| sum ^ x.hash(s, e))
        }
    }
}
mod input_scanner {
    pub struct Scanner {
        bytes: Vec<u8>,
        begin: usize,
        end: usize,
    }

    impl Scanner {
        pub fn new() -> Self {
            let mut buffer: Vec<u8> = Vec::with_capacity(2000);
            std::io::Read::read_to_end(&mut std::io::stdin(), &mut buffer).unwrap();
            let end = Scanner::step_item(&buffer, 0);
            Scanner {
                bytes: buffer,
                begin: 0,
                end: end,
            }
        }
        pub fn next<T>(&mut self) -> T
        where
            T: std::str::FromStr,
            T::Err: std::fmt::Debug,
        {
            let s: &str =
                unsafe { std::str::from_utf8_unchecked(&self.bytes[self.begin..self.end]) };
            let ret: T = s.parse::<T>().unwrap();
            self.step();
            ret
        }
        pub fn next_vec<T>(&mut self, n: usize) -> Vec<T>
        where
            T: std::str::FromStr,
            T::Err: std::fmt::Debug,
        {
            let mut v: Vec<T> = Vec::with_capacity(n);
            for _i in 0..n {
                v.push(self.next());
            }
            v
        }
        pub fn next_chars(&mut self) -> Vec<u8> {
            let r = Vec::from(&self.bytes[self.begin..self.end]);
            self.step();
            r
        }
        fn step(&mut self) {
            self.begin = Scanner::step_whitespace(&self.bytes, self.end);
            self.end = Scanner::step_item(&self.bytes, self.begin);
        }
        fn step_whitespace(s: &Vec<u8>, idx: usize) -> usize {
            let mut r = idx;
            while r < s.len() && (s[r] == ' ' as u8 || s[r] == '\n' as u8 || s[r] == '\r' as u8) {
                r += 1;
            }
            r
        }
        fn step_item(s: &Vec<u8>, idx: usize) -> usize {
            let mut r = idx;
            while r < s.len() && s[r] != ' ' as u8 && s[r] != '\n' as u8 && s[r] != '\r' as u8 {
                r += 1;
            }
            r
        }
    }
}


#![allow(unused_imports)]
#![allow(dead_code)]
use datastructure::*;
use grapth::*;
use input_scanner::*;
use math::*;
use string_algorithm::*;
use util::*;

use std::cmp;
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};

fn main() {
    let mut scan = Scanner::new();
    let s = scan.next_chars();
    let bad = scan.next_chars();
    let k: i32 = scan.next();
    let mrh = MultiRollingHash::new(&s, &[17, 1000000007]);
    let mut set: HashSet<u64> = HashSet::new();

    for len in 1..s.len() + 1 {
        let mut cnt: i32 = 0;
        for i in 0..len - 1 {
            if bad[s[i] as usize - 'a' as usize] == '0' {
                cnt += 1;
            }
        }
        for i in 0..s.len() + 1 - len {
            if bad[s[i + len - 1] as usize - 'a' as usize] == '0' {
                cnt += 1;
            }
            if cnt <= k {
                set.insert(mrh.hash(i, i + len));
            }
            if bad[s[i] as usize - 'a' as usize] == '0' {
                cnt -= 1;
            }
        }
    }
    println!("{}", set.len());
}

mod datastructure {}
mod grapth {}
mod math {}
mod util {}
mod string_algorithm {
    pub struct RollingHash {
        hash: Vec<u64>,
        inv: Vec<u64>,
    }

    impl RollingHash {
        fn inverse(mut x: u64) -> u64 {
            let mut ret: u64 = 1;
            for _i in 0..64 {
                ret = ret.wrapping_mul(x);
                x = x.wrapping_mul(x);
            }
            ret
        }
        pub fn new(text: &[char], base: u64) -> Self {
            assert!(base % 2 == 1);
            let inv = RollingHash::inverse(base);
            let mut b = base;
            let mut h_i = 0u64;
            let mut inv_i = 1u64;
            let mut hash: Vec<u64> = Vec::with_capacity(text.len() + 1);
            let mut invs: Vec<u64> = Vec::with_capacity(text.len() + 1);
            hash.push(h_i);
            invs.push(inv_i);
            for ch in text {
                b = b.wrapping_mul(base);
                h_i = b.wrapping_mul(*ch as u64).wrapping_add(h_i);
                hash.push(h_i);
                inv_i = inv_i.wrapping_mul(inv);
                invs.push(inv_i);
            }
            RollingHash {
                hash: hash,
                inv: invs,
            }
        }
        // [s, e)
        pub fn hash(&self, s: usize, e: usize) -> u64 {
            (self.hash[e].wrapping_sub(self.hash[s])).wrapping_mul(self.inv[s])
        }
    }

    pub struct MultiRollingHash {
        rhs: Vec<RollingHash>,
    }

    impl MultiRollingHash {
        pub fn new(text: &[char], bases: &[u64]) -> Self {
            let mut rhs = Vec::with_capacity(bases.len());
            for b in bases {
                rhs.push(RollingHash::new(text, *b));
            }
            MultiRollingHash { rhs: rhs }
        }
        pub fn hash(&self, s: usize, e: usize) -> u64 {
            self.rhs.iter().fold(0, |sum, x| sum ^ x.hash(s, e))
        }
    }
}
mod input_scanner {
    pub struct Scanner {
        bytes: Vec<u8>,
        begin: usize,
        end: usize,
    }

    impl Scanner {
        pub fn new() -> Self {
            let mut buffer: Vec<u8> = Vec::new();
            std::io::Read::read_to_end(&mut std::io::stdin(), &mut buffer).unwrap();
            let end = Scanner::step_item(&buffer, 0);
            Scanner {
                bytes: buffer,
                begin: 0,
                end: end,
            }
        }
        pub fn next<T>(&mut self) -> T
        where
            T: std::str::FromStr,
            T::Err: std::fmt::Debug,
        {
            let s: &str =
                unsafe { std::str::from_utf8_unchecked(&self.bytes[self.begin..self.end]) };
            let ret: T = s.parse::<T>().unwrap();
            self.begin = Scanner::step_whitespace(&self.bytes, self.end);
            self.end = Scanner::step_item(&self.bytes, self.begin);
            ret
        }
        pub fn next_vec<T>(&mut self, n: usize) -> Vec<T>
        where
            T: std::str::FromStr,
            T::Err: std::fmt::Debug,
        {
            let mut v: Vec<T> = Vec::with_capacity(n);
            for _i in 0..n {
                v.push(self.next());
            }
            v
        }
        pub fn next_chars(&mut self) -> Vec<char> {
            let s: String = self.next();
            s.chars().collect::<Vec<char>>()
        }
        fn step_whitespace(s: &Vec<u8>, idx: usize) -> usize {
            let mut r = idx;
            while r < s.len() && (s[r] == ' ' as u8 || s[r] == '\n' as u8 || s[r] == '\r' as u8) {
                r += 1;
            }
            r
        }
        fn step_item(s: &Vec<u8>, idx: usize) -> usize {
            let mut r = idx;
            while r < s.len() && s[r] != ' ' as u8 && s[r] != '\n' as u8 && s[r] != '\r' as u8 {
                r += 1;
            }
            r
        }
    }
}


#![allow(unused_imports)]
#![allow(dead_code)]
use datastructure::*;
use grapth::*;
use input_scanner::*;
use math::*;
use string_algorithm::*;
use util::*;

use std::cmp;
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};

fn main() {
    let mut scan = Scanner::new();
    let s = scan.next_chars();
    let bad = scan.next_chars();
    let k: i32 = scan.next();
    let rh1 = RollingHash::new(&s, 17);
    let rh2 = RollingHash::new(&s, 1000000007);
    let mut set: HashSet<(u64, u64)> = HashSet::new();

    for len in 1..s.len() + 1 {
        let mut cnt: i32 = 0;
        for i in 0..len - 1 {
            if bad[s[i] as usize - 'a' as usize] == '0' {
                cnt += 1;
            }
        }
        for i in 0..s.len() + 1 - len {
            if bad[s[i + len - 1] as usize - 'a' as usize] == '0' {
                cnt += 1;
            }
            if cnt <= k {
                set.insert((rh1.hash(i, i+len), rh2.hash(i, i+len)));
            }
            if bad[s[i] as usize - 'a' as usize] == '0' {
                cnt -= 1;
            }
        }
    }
    println!("{}", set.len());
}

mod datastructure {}
mod grapth {}
mod math {}
mod util {}
mod string_algorithm {
    pub struct RollingHash {
        hash: Vec<u64>,
        inv: Vec<u64>,
    }

    impl RollingHash {
        fn inverse(mut x: u64) -> u64 {
            let mut ret: u64 = 1;
            for _i in 0..64 {
                ret = ret.wrapping_mul(x);
                x = x.wrapping_mul(x);
            }
            ret
        }
        pub fn new(text: &[char], base: u64) -> Self {
            let inv = RollingHash::inverse(base);
            let mut b = base;
            let mut h_i = 0u64;
            let mut inv_i = 1u64;
            let mut hash: Vec<u64> = Vec::with_capacity(text.len() + 1);
            let mut invs: Vec<u64> = Vec::with_capacity(text.len() + 1);
            hash.push(h_i);
            invs.push(inv_i);
            for ch in text {
                b = b.wrapping_mul(base);
                h_i = b.wrapping_mul(*ch as u64).wrapping_add(h_i);
                hash.push(h_i);
                inv_i = inv_i.wrapping_mul(inv);
                invs.push(inv_i);
            }
            RollingHash {
                hash: hash,
                inv: invs,
            }
        }
        // [s, e)
        pub fn hash(&self, s: usize, e: usize) -> u64 {
            (self.hash[e].wrapping_sub(self.hash[s])).wrapping_mul(self.inv[s])
        }
    }
}
mod input_scanner {
    pub struct Scanner {
        line: Vec<String>,
        idx: usize,
    }

    impl Scanner {
        pub fn new() -> Self {
            let mut buffer = String::new();
            std::io::Read::read_to_string(&mut std::io::stdin(), &mut buffer).unwrap();
            Scanner {
                line: buffer
                    .trim()
                    .split_ascii_whitespace()
                    .collect::<Vec<&str>>()
                    .iter()
                    .map(|&s| String::from(s))
                    .collect(),
                idx: 0,
            }
        }
        pub fn next<T>(&mut self) -> T
        where
            T: std::str::FromStr,
            T::Err: std::fmt::Debug,
        {
            let ret: T = self.line[self.idx].parse::<T>().unwrap();
            self.idx += 1;
            ret
        }
        pub fn next_vec<T>(&mut self, n: usize) -> Vec<T>
        where
            T: std::str::FromStr,
            T::Err: std::fmt::Debug,
        {
            let mut v: Vec<T> = Vec::with_capacity(n);
            for _i in 0..n {
                v.push(self.next());
            }
            v
        }
        pub fn next_chars(&mut self) -> Vec<char> {
            let s: String = self.next();
            s.chars().collect::<Vec<char>>()
        }
    }
}


#![allow(unused_imports)]
#![allow(dead_code)]
use datastructure::*;
use grapth::*;
use input_scanner::*;
use math::*;
use string_algorithm::*;
use util::*;

use std::cmp;
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};

fn main() {
    let mut scan = Scanner::new();
    let s = scan.next_chars();
    let bad = scan.next_chars();
    let k: i32 = scan.next();
    let rh1 = RollingHash::new(&s, 17);
    let rh2 = RollingHash::new(&s, 1000000007);
    let mut set: HashSet<u64> = HashSet::new();

    for len in 1..s.len() + 1 {
        let mut cnt: i32 = 0;
        for i in 0..len - 1 {
            if bad[s[i] as usize - 'a' as usize] == '0' {
                cnt += 1;
            }
        }
        for i in 0..s.len() + 1 - len {
            if bad[s[i + len - 1] as usize - 'a' as usize] == '0' {
                cnt += 1;
            }
            if cnt <= k {
                set.insert(rh1.hash(i, i + len)^ rh2.hash(i, i + len));
            }
            if bad[s[i] as usize - 'a' as usize] == '0' {
                cnt -= 1;
            }
        }
    }
    println!("{}", set.len());
}

mod datastructure {}
mod grapth {}
mod math {}
mod util {}
mod string_algorithm {
    pub struct RollingHash {
        hash: Vec<u64>,
        inv: Vec<u64>,
    }

    impl RollingHash {
        fn inverse(mut x: u64) -> u64 {
            let mut ret: u64 = 1;
            for _i in 0..64 {
                ret = ret.wrapping_mul(x);
                x = x.wrapping_mul(x);
            }
            ret
        }
        pub fn new(text: &[char], base: u64) -> Self {
            assert!(base % 2 == 1);
            let inv = RollingHash::inverse(base);
            let mut b = base;
            let mut h_i = 0u64;
            let mut inv_i = 1u64;
            let mut hash: Vec<u64> = Vec::with_capacity(text.len() + 1);
            let mut invs: Vec<u64> = Vec::with_capacity(text.len() + 1);
            hash.push(h_i);
            invs.push(inv_i);
            for ch in text {
                b = b.wrapping_mul(base);
                h_i = b.wrapping_mul(*ch as u64).wrapping_add(h_i);
                hash.push(h_i);
                inv_i = inv_i.wrapping_mul(inv);
                invs.push(inv_i);
            }
            RollingHash {
                hash: hash,
                inv: invs,
            }
        }
        // [s, e)
        pub fn hash(&self, s: usize, e: usize) -> u64 {
            (self.hash[e].wrapping_sub(self.hash[s])).wrapping_mul(self.inv[s])
        }
    }
}
mod input_scanner {
    pub struct Scanner {
        line: Vec<String>,
        idx: usize,
    }

    impl Scanner {
        pub fn new() -> Self {
            let mut buffer = String::new();
            std::io::Read::read_to_string(&mut std::io::stdin(), &mut buffer).unwrap();
            Scanner {
                line: buffer
                    .trim()
                    .split_ascii_whitespace()
                    .collect::<Vec<&str>>()
                    .iter()
                    .map(|&s| String::from(s))
                    .collect(),
                idx: 0,
            }
        }
        pub fn next<T>(&mut self) -> T
        where
            T: std::str::FromStr,
            T::Err: std::fmt::Debug,
        {
            let ret: T = self.line[self.idx].parse::<T>().unwrap();
            self.idx += 1;
            ret
        }
        pub fn next_vec<T>(&mut self, n: usize) -> Vec<T>
        where
            T: std::str::FromStr,
            T::Err: std::fmt::Debug,
        {
            let mut v: Vec<T> = Vec::with_capacity(n);
            for _i in 0..n {
                v.push(self.next());
            }
            v
        }
        pub fn next_chars(&mut self) -> Vec<char> {
            let s: String = self.next();
            s.chars().collect::<Vec<char>>()
        }
    }
}


#![allow(unused_imports)]
#![allow(dead_code)]
use datastructure::*;
use grapth::*;
use input_scanner::*;
use math::*;
use string_algorithm::*;
use util::*;

use std::cmp;
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};

fn main() {
    let mut scan = Scanner::new();
    let s = scan.next_chars();
    let bad = scan.next_chars();
    let k: i32 = scan.next();
    let mrh = MultiRollingHash::new(&s, &[17, 1000000007]);
    let mut set: HashSet<u64> = HashSet::new();

    for len in 1..s.len() + 1 {
        let mut cnt: i32 = 0;
        for i in 0..len - 1 {
            if bad[s[i] as usize - 'a' as usize] == '0' {
                cnt += 1;
            }
        }
        for i in 0..s.len() + 1 - len {
            if bad[s[i + len - 1] as usize - 'a' as usize] == '0' {
                cnt += 1;
            }
            if cnt <= k {
                set.insert(mrh.hash(i, i + len));
            }
            if bad[s[i] as usize - 'a' as usize] == '0' {
                cnt -= 1;
            }
        }
    }
    println!("{}", set.len());
}

mod datastructure {}
mod grapth {}
mod math {}
mod util {}
mod string_algorithm {
    pub struct RollingHash {
        hash: Vec<u64>,
        inv: Vec<u64>,
    }

    impl RollingHash {
        fn inverse(mut x: u64) -> u64 {
            let mut ret: u64 = 1;
            for _i in 0..64 {
                ret = ret.wrapping_mul(x);
                x = x.wrapping_mul(x);
            }
            ret
        }
        pub fn new(text: &[char], base: u64) -> Self {
            assert!(base % 2 == 1);
            let inv = RollingHash::inverse(base);
            let mut b = base;
            let mut h_i = 0u64;
            let mut inv_i = 1u64;
            let mut hash: Vec<u64> = Vec::with_capacity(text.len() + 1);
            let mut invs: Vec<u64> = Vec::with_capacity(text.len() + 1);
            hash.push(h_i);
            invs.push(inv_i);
            for ch in text {
                b = b.wrapping_mul(base);
                h_i = b.wrapping_mul(*ch as u64).wrapping_add(h_i);
                hash.push(h_i);
                inv_i = inv_i.wrapping_mul(inv);
                invs.push(inv_i);
            }
            RollingHash {
                hash: hash,
                inv: invs,
            }
        }
        // [s, e)
        pub fn hash(&self, s: usize, e: usize) -> u64 {
            (self.hash[e].wrapping_sub(self.hash[s])).wrapping_mul(self.inv[s])
        }
    }

    pub struct MultiRollingHash {
        rhs: Vec<RollingHash>,
    }

    impl MultiRollingHash {
        pub fn new(text: &[char], bases: &[u64]) -> Self {
            let mut rhs = Vec::with_capacity(bases.len());
            for b in bases {
                rhs.push(RollingHash::new(text, *b));
            }
            MultiRollingHash { rhs: rhs }
        }
        pub fn hash(&self, s: usize, e: usize) -> u64 {
            self.rhs.iter().fold(0, |sum, x| sum ^ x.hash(s, e))
        }
    }
}
mod input_scanner {
    pub struct Scanner {
        bytes: Vec<u8>,
        begin: usize,
        end: usize,
    }

    impl Scanner {
        pub fn new() -> Self {
            let mut buffer: Vec<u8> = Vec::with_capacity(2000);
            std::io::Read::read_to_end(&mut std::io::stdin(), &mut buffer).unwrap();
            let end = Scanner::step_item(&buffer, 0);
            Scanner {
                bytes: buffer,
                begin: 0,
                end: end,
            }
        }
        pub fn next<T>(&mut self) -> T
        where
            T: std::str::FromStr,
            T::Err: std::fmt::Debug,
        {
            let s: &str =
                unsafe { std::str::from_utf8_unchecked(&self.bytes[self.begin..self.end]) };
            let ret: T = s.parse::<T>().unwrap();
            self.begin = Scanner::step_whitespace(&self.bytes, self.end);
            self.end = Scanner::step_item(&self.bytes, self.begin);
            ret
        }
        pub fn next_vec<T>(&mut self, n: usize) -> Vec<T>
        where
            T: std::str::FromStr,
            T::Err: std::fmt::Debug,
        {
            let mut v: Vec<T> = Vec::with_capacity(n);
            for _i in 0..n {
                v.push(self.next());
            }
            v
        }
        pub fn next_chars(&mut self) -> Vec<char> {
            let s: String = self.next();
            s.chars().collect::<Vec<char>>()
        }
        fn step_whitespace(s: &Vec<u8>, idx: usize) -> usize {
            let mut r = idx;
            while r < s.len() && (s[r] == ' ' as u8 || s[r] == '\n' as u8 || s[r] == '\r' as u8) {
                r += 1;
            }
            r
        }
        fn step_item(s: &Vec<u8>, idx: usize) -> usize {
            let mut r = idx;
            while r < s.len() && s[r] != ' ' as u8 && s[r] != '\n' as u8 && s[r] != '\r' as u8 {
                r += 1;
            }
            r
        }
    }
}


#![allow(unused_imports)]
#![allow(dead_code)]
use datastructure::*;
use grapth::*;
use input_scanner::*;
use math::*;
use string_algorithm::*;
use util::*;

use std::cmp;
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};

fn main() {
    let mut scan = Scanner::new();
    let s = scan.next_chars();
    let bad = scan.next_chars();
    let k: i32 = scan.next();
    let mrh = MultiRollingHash::new(&s, &[17, 1000000007]);
    let mut set: HashSet<u64> = HashSet::new();

    for len in 1..s.len() + 1 {
        let mut cnt: i32 = 0;
        for i in 0..len - 1 {
            if bad[s[i] as usize - 'a' as usize] == '0' {
                cnt += 1;
            }
        }
        for i in 0..s.len() + 1 - len {
            if bad[s[i + len - 1] as usize - 'a' as usize] == '0' {
                cnt += 1;
            }
            if cnt <= k {
                set.insert(mrh.hash(i, i + len));
            }
            if bad[s[i] as usize - 'a' as usize] == '0' {
                cnt -= 1;
            }
        }
    }
    println!("{}", set.len());
}

mod datastructure {}
mod grapth {}
mod math {}
mod util {}
mod string_algorithm {
    pub struct RollingHash {
        hash: Vec<u64>,
        inv: Vec<u64>,
    }

    impl RollingHash {
        fn inverse(mut x: u64) -> u64 {
            let mut ret: u64 = 1;
            for _i in 0..64 {
                ret = ret.wrapping_mul(x);
                x = x.wrapping_mul(x);
            }
            ret
        }
        pub fn new(text: &[char], base: u64) -> Self {
            assert!(base % 2 == 1);
            let inv = RollingHash::inverse(base);
            let mut b = base;
            let mut h_i = 0u64;
            let mut inv_i = 1u64;
            let mut hash: Vec<u64> = Vec::with_capacity(text.len() + 1);
            let mut invs: Vec<u64> = Vec::with_capacity(text.len() + 1);
            hash.push(h_i);
            invs.push(inv_i);
            for ch in text {
                b = b.wrapping_mul(base);
                h_i = b.wrapping_mul(*ch as u64).wrapping_add(h_i);
                hash.push(h_i);
                inv_i = inv_i.wrapping_mul(inv);
                invs.push(inv_i);
            }
            RollingHash {
                hash: hash,
                inv: invs,
            }
        }
        // [s, e)
        pub fn hash(&self, s: usize, e: usize) -> u64 {
            (self.hash[e].wrapping_sub(self.hash[s])).wrapping_mul(self.inv[s])
        }
    }

    pub struct MultiRollingHash {
        rhs: Vec<RollingHash>,
    }

    impl MultiRollingHash {
        pub fn new(text: &[char], bases: &[u64]) -> Self {
            let mut rhs = Vec::with_capacity(bases.len());
            for b in bases {
                rhs.push(RollingHash::new(text, *b));
            }
            MultiRollingHash { rhs: rhs }
        }
        pub fn hash(&self, s: usize, e: usize) -> u64 {
            self.rhs.iter().fold(0, |sum, x| sum ^ x.hash(s, e))
        }
    }
}
mod input_scanner {
    pub struct Scanner {
        line: Vec<String>,
        idx: usize,
    }

    impl Scanner {
        pub fn new() -> Self {
            let mut buffer: Vec<u8> = Vec::new();
            std::io::Read::read_to_end(&mut std::io::stdin(), &mut buffer).unwrap();
            let b: &str = unsafe { std::str::from_utf8_unchecked(&mut buffer) };
            Scanner {
                line: b
                    .trim()
                    .split_ascii_whitespace()
                    .collect::<Vec<&str>>()
                    .iter()
                    .map(|&s| String::from(s))
                    .collect(),
                idx: 0,
            }
        }
        pub fn next<T>(&mut self) -> T
        where
            T: std::str::FromStr,
            T::Err: std::fmt::Debug,
        {
            let ret: T = self.line[self.idx].parse::<T>().unwrap();
            self.idx += 1;
            ret
        }
        pub fn next_vec<T>(&mut self, n: usize) -> Vec<T>
        where
            T: std::str::FromStr,
            T::Err: std::fmt::Debug,
        {
            let mut v: Vec<T> = Vec::with_capacity(n);
            for _i in 0..n {
                v.push(self.next());
            }
            v
        }
        pub fn next_chars(&mut self) -> Vec<char> {
            let s: String = self.next();
            s.chars().collect::<Vec<char>>()
        }
    }
}


pub struct Scanner {
    bytes: Vec<u8>,
    begin: usize,
    end: usize,
}

impl Scanner {
    pub fn new() -> Self {
        let mut buffer: Vec<u8> = Vec::with_capacity(2000);
        std::io::Read::read_to_end(&mut std::io::stdin(), &mut buffer).unwrap();
        let end = Scanner::step_item(&buffer, 0);
        Scanner {
            bytes: buffer,
            begin: 0,
            end: end,
        }
    }
    pub fn next<T>(&mut self) -> T
    where
        T: std::str::FromStr,
        T::Err: std::fmt::Debug,
    {
        let s: &str = unsafe { std::str::from_utf8_unchecked(&self.bytes[self.begin..self.end]) };
        let ret: T = s.parse::<T>().unwrap();
        self.begin = Scanner::step_whitespace(&self.bytes, self.end);
        self.end = Scanner::step_item(&self.bytes, self.begin);
        ret
    }
    pub fn next_vec<T>(&mut self, n: usize) -> Vec<T>
    where
        T: std::str::FromStr,
        T::Err: std::fmt::Debug,
    {
        let mut v: Vec<T> = Vec::with_capacity(n);
        for _i in 0..n {
            v.push(self.next());
        }
        v
    }
    pub fn next_chars(&mut self) -> Vec<char> {
        let s: String = self.next();
        s.chars().collect::<Vec<char>>()
    }
    fn step_whitespace(s: &Vec<u8>, idx: usize) -> usize {
        let mut r = idx;
        while r < s.len() && (s[r] == ' ' as u8 || s[r] == '\n' as u8 || s[r] == '\r' as u8) {
            r += 1;
        }
        r
    }
    fn step_item(s: &Vec<u8>, idx: usize) -> usize {
        let mut r = idx;
        while r < s.len() && s[r] != ' ' as u8 && s[r] != '\n' as u8 && s[r] != '\r' as u8 {
            r += 1;
        }
        r
    }
}


package main

// http://codeforces.com/problemset/problem/271/D

import (
	"bufio"
	"fmt"
	"os"
	"sort"
)

const mx = 1500

var (
	reader *bufio.Reader = bufio.NewReader(os.Stdin)
	writer *bufio.Writer = bufio.NewWriter(os.Stdout)
	Debug                = true

	mtable [mx]uint64

	pri = uint64(1004271249911446763)
)

func Printf(f string, a ...interface{}) { fmt.Fprintf(writer, f, a...) }
func Scanf(f string, a ...interface{})  { fmt.Fscanf(reader, f, a...) }

func Dprint(format string, a ...interface{}) {
	if Debug {
		fmt.Fprintf(os.Stderr, format+"\n", a...)
	}
}

func main() {
	defer writer.Flush()

	// Initialize mtable.
	mtable[0] = 1
	for i := 1; i < 1500; i++ {
		mtable[i] = (mtable[i-1] * 31) % pri
	}

	var s, goodS string
	var k int
	Scanf("%s\n%s\n%d", &s, &goodS, &k)
	Dprint("s=%s,good=%s,k=%d", s, goodS, k)

	// Good says whether an entry is good.
	good := make([]bool, len(goodS))
	for i := 0; i < len(goodS); i++ {
		good[i] = goodS[i] == '1'
	}

	var hashes []uint64

	for start := 0; start < len(s); start++ {
		var hash uint64
		var bads int
		for end := start; end < len(s); end++ {
			si := uint64(s[end] - 'a')
			if !good[si] {
				bads++
			}
			// Dprint("%v, %d, bads=%v,k=%v", good, si, bads, k)
			if bads > k {
				// Too many bad characters.
				break
			}
			hash += ((si + 1) * mtable[end-start]) % pri
			hashes = append(hashes, hash)
			//Dprint("%s=%d", s[start:end+1], hash)
		}
	}

	sort.Slice(hashes, func(i, j int) bool {
		return hashes[i] < hashes[j]
	})

	unique := 1
	for i := 1; i < len(hashes); i++ {
		if hashes[i] != hashes[i-1] {
			unique++
		}
	}

	if len(hashes) == 0 {
		unique = 0
	}
	//Dprint("%v", hashes)
	Printf("%d\n", unique)
}


package main

// http://codeforces.com/problemset/problem/271/D

import (
	"bufio"
	"fmt"
	"os"
	"sort"
)

const mx = 1500

var (
	reader *bufio.Reader = bufio.NewReader(os.Stdin)
	writer *bufio.Writer = bufio.NewWriter(os.Stdout)
	Debug                = true

	mtable [mx]uint64

	pri = uint64(1004271249911446763)
)

func Printf(f string, a ...interface{}) { fmt.Fprintf(writer, f, a...) }
func Scanf(f string, a ...interface{})  { fmt.Fscanf(reader, f, a...) }

func Dprint(format string, a ...interface{}) {
	if Debug {
		fmt.Fprintf(os.Stderr, format+"\n", a...)
	}
}

func main() {
	defer writer.Flush()

	// Initialize mtable.
	mtable[0] = 1
	for i := 1; i < 1500; i++ {
		mtable[i] = (mtable[i-1] * 31) % pri
	}

	var s, goodS string
	var k int
	Scanf("%s\n%s\n%d", &s, &goodS, &k)
	Dprint("s=%s,good=%s,k=%d", s, goodS, k)

	// Good says whether an entry is good.
	good := make([]bool, len(goodS))
	for i := 0; i < len(goodS); i++ {
		good[i] = goodS[i] == '1'
	}

	var hashes []uint64

	for start := 0; start < len(s); start++ {
		var hash uint64
		var bads int
		for end := start; end < len(s); end++ {
			si := uint64(s[end] - 'a')
			if !good[si] {
				bads++
			}
			if bads > k {
				// Too many bad characters.
				break
			}
			hash += ((si + 1) * mtable[end-start]) % pri
			hashes = append(hashes, hash)
			//Dprint("%s=%d", s[start:end+1], hash)
		}
	}

	sort.Slice(hashes, func(i, j int) bool {
		return hashes[i] < hashes[j]
	})

	unique := 1
	for i := 1; i < len(hashes); i++ {
		if hashes[i] != hashes[i-1] {
			unique++
		}
	}
	//Dprint("%v", hashes)
	Printf("%d\n", unique)
}


package main

import (
	"bufio"
	"fmt"
	"os"
)

var goodChars string
var k int
var goodSubstrings map[string]bool

func main() {
	// file, _ := os.Open("input")
	file := os.Stdin
	reader := bufio.NewReader(file)
	var s string
	fmt.Fscanf(reader, "%s\n%s\n%d", &s, &goodChars, &k)
	goodSubstrings = map[string]bool{}

	trie := &trie{}

	for i := 0; i < len(s); i++ {
		for j := i + 1; j <= len(s); j++ {
			subString := s[i:j]
			trie.insert(subString, 0, 0)
		}
	}

	fmt.Println(len(goodSubstrings))
	return
}

type trie struct {
	value int
	ok    bool
	chars [26]*trie
}

func (e *trie) insert(s string, i, v int) {
	if v > k {
		return
	}

	if i == len(s) {
		e.value = v

		if v <= k {
			e.ok = true
			goodSubstrings[s] = true
		}
		return
	}

	pos := s[i] - 'a'
	if goodChars[pos] != '1' {
		v++
	}

	if e.chars[pos] == nil {
		newNode := &trie{}
		e.chars[pos] = newNode
	}

	e.chars[pos].insert(s, i+1, v)
}


package main

import (
	"bufio"
	"fmt"
	"os"
)

var goodChars string
var result, k int

func main() {
	// file, _ := os.Open("input")
	file := os.Stdin
	reader := bufio.NewReader(file)
	var s string
	fmt.Fscanf(reader, "%s\n%s\n%d", &s, &goodChars, &k)
	result = 0

	trie := &trie{}

	for i := 0; i < len(s); i++ {
		for j := i + 1; j <= len(s); j++ {
			subString := s[i:j]
			trie.insert(subString, 0, 0)
		}
	}

	fmt.Println(trie.count())
	return
}

type trie struct {
	value int
	ok    bool
	chars [26]*trie
}

func (e *trie) insert(s string, i, v int) {
	if i == len(s) {
		e.value = v

		if v <= k {
			e.ok = true
		}
		return
	}

	pos := s[i] - 'a'
	if goodChars[pos] != '1' {
		v++
	}

	if e.chars[pos] == nil {
		newNode := &trie{}
		e.chars[pos] = newNode
	}

	e.chars[pos].insert(s, i+1, v)
}

func (e *trie) count() int {
	if e == nil {
		return 0
	}

	count := 0
	for _, c := range e.chars {
		count += c.count()
	}
	if e.ok {
		count++
	}

	return count
}


package main

import (
	"bufio"
	"fmt"
	"os"
)

var goodChars string
var result, k int

func main() {
	// file, _ := os.Open("input")
	file := os.Stdin
	reader := bufio.NewReader(file)
	var s string
	fmt.Fscanf(reader, "%s\n%s\n%d", &s, &goodChars, &k)
	result = 0
	trie := &trie{}

	for i := 0; i < len(s); i++ {
		for j := i + 1; j <= len(s); j++ {
			subString := s[i:j]
			trie.insert(subString, 0, 0)
		}
	}

	fmt.Println(trie.count())
	return
}

type trie struct {
	value int
	ok    bool
	chars [26]*trie
}

func (e *trie) insert(s string, i, v int) {
	if v > k {
		return
	}

	if i == len(s) {
		e.value = v

		if v <= k {
			e.ok = true
		}
		return
	}

	pos := s[i] - 'a'
	if goodChars[pos] != '1' {
		v++
	}

	if e.chars[pos] == nil {
		newNode := &trie{}
		e.chars[pos] = newNode
	}

	e.chars[pos].insert(s, i+1, v)
}

func (e *trie) count() int {
	if e == nil {
		return 0
	}

	count := 0
	for _, c := range e.chars {
		count += c.count()
	}
	if e.ok {
		count++
	}

	return count
}


package main

import (
	"bufio"
	"fmt"
	"os"
)

var goodChars string
var k, result int

func main() {
	// file, _ := os.Open("input")
	file := os.Stdin
	reader := bufio.NewReader(file)
	var s string
	fmt.Fscanf(reader, "%s\n%s\n%d", &s, &goodChars, &k)

	trie := &trie{}
	n := len(s)
	for i := 0; i < n; i++ {
		subString := s[i:n]
		trie.insert(subString, 0, 0)
	}

	fmt.Println(result)
	return
}

type trie struct {
	chars [26]*trie
}

func (e *trie) insert(s string, i, v int) {
	if i == len(s) {
		return
	}

	pos := s[i] - 'a'
	if goodChars[pos] != '1' {
		v++
	}

	if e.chars[pos] == nil {
		newNode := &trie{}
		e.chars[pos] = newNode

		if v <= k {
			result++
		}
	}

	e.chars[pos].insert(s, i+1, v)
}


package main

import (
	"bufio"
	"fmt"
	"os"
)

var goodChars string
var k int

func main() {
	// file, _ := os.Open("input")
	file := os.Stdin
	reader := bufio.NewReader(file)
	var s string
	fmt.Fscanf(reader, "%s\n%s\n%d", &s, &goodChars, &k)

	trie := &trie{}
	n := len(s)
	for i := 0; i < n; i++ {
		subString := s[i:n]
		trie.insert(subString, 0, 0)
	}

	fmt.Println(trie.count() - 1)
	return
}

type trie struct {
	value int
	ok    bool
	chars [26]*trie
}

func (e *trie) insert(s string, i, v int) {
	if i == len(s) {
		return
	}

	pos := s[i] - 'a'
	if goodChars[pos] != '1' {
		v++
	}

	if e.chars[pos] == nil {
		newNode := &trie{}
		e.chars[pos] = newNode
	}

	e.chars[pos].value = v
	e.chars[pos].insert(s, i+1, v)
}

func (e *trie) count() int {
	if e == nil {
		return 0
	}

	count := 0
	for _, c := range e.chars {
		count += c.count()
	}

	if e.value <= k {
		count++
	}

	return count
}


package main

import (
	"bufio"
	"fmt"
	"os"
)

var (
	base   = uint64(311)
	hash   = []uint64{}
	hashes = map[uint64]bool{}
)

func solve(s string, k int, n int, value string) int {
	count, hash := 0, uint64(0)
	var id byte

	for i := range s {
		count = 0
		hash = 0
		for j := i; j < n; j++ {
			id = s[j] - 'a'
			if value[id] == '0' {
				count++
				if count > k {
					break
				}
			}
			hash = hash*base + uint64(s[j])
			hashes[hash] = true
		}
	}

	return len(hashes)
}

func main() {
	r := bufio.NewReader(os.Stdin)
	var str, value string
	var k int

	fmt.Fscanf(r, "%s\n", &str)
	fmt.Fscanf(r, "%s\n", &value)
	fmt.Fscanf(r, "%d\n", &k)
	hash = make([]uint64, len(str))

	fmt.Fprintf(os.Stdout, "%d\n", solve(str, k, len(str), value))
}


package main

import (
	"bufio"
	"fmt"
	"os"
)

var (
	base   = uint64(27)
	maxN   = 1500 + 10
	hash   = make([]uint64, maxN)
	hashes = map[uint64]bool{}
)

func solve(s string, k int, n int, value string) int {
	count := 0
	var id byte

	for i := range s {
		count = 0
		for j := i; j < n; j++ {
			id = s[j] - 'a'
			if value[id] == '0' {
				count++
				if count > k {
					break
				}
			}
			hashes[getHash(s[i:j+1])] = true
		}
	}

	return len(hashes)
}

func getHash(s string) uint64 {
	hash[0] = uint64(s[0])

	for i := 1; i < len(s); i++ {
		hash[i] = (hash[i-1]*base + uint64(s[i]))
	}

	return hash[len(s)-1]
}

func main() {
	r := bufio.NewReader(os.Stdin)
	var str, value string
	var k int

	fmt.Fscanf(r, "%s\n", &str)
	fmt.Fscanf(r, "%s\n", &value)
	fmt.Fscanf(r, "%d\n", &k)

	fmt.Println(solve(str, k, len(str), value))
}


package main

import (
	"bufio"
	"fmt"
	"os"
)

var (
	base   = uint64(127)
	hash   = []uint64{}
	hashes = map[uint64]bool{}
)

func solve(s string, k int, n int, value string) int {
	count, hash := 0, uint64(0)
	var id byte

	for i := range s {
		count = 0
		hash = 0
		for j := i; j < n; j++ {
			id = s[j] - 'a'
			if value[id] == '0' {
				count++
			}
			if count <= k {
				hash = hash*base + uint64(s[j])
				hashes[hash] = true
			} else {
				break
			}
		}
	}

	return len(hashes)
}

func main() {
	r := bufio.NewReader(os.Stdin)
	var str, value string
	var k int

	fmt.Fscanf(r, "%s\n", &str)
	fmt.Fscanf(r, "%s\n", &value)
	fmt.Fscanf(r, "%d\n", &k)
	hash = make([]uint64, len(str))

	fmt.Fprintf(os.Stdout, "%d\n", solve(str, k, len(str), value))
}


package main

import (
	"bufio"
	"fmt"
	"os"
)

var (
	base   = uint64(127)
	mod    = uint64(1e9 + 7)
	hash   = []uint64{}
	hashes = map[uint64]bool{}
)

func solve(s string, k int, n int, value string) int {
	count, hash := 0, uint64(0)
	var id byte

	for i := range s {
		count = 0
		hash = 0
		for j := i; j < n; j++ {
			id = s[j] - 'a'
			if value[id] == '0' {
				count++
				if count > k {
					break
				}
			}
			hash = (hash*base + uint64(s[j])) % mod
			hashes[hash] = true
		}
	}

	return len(hashes)
}

func main() {
	r := bufio.NewReader(os.Stdin)
	var str, value string
	var k int

	fmt.Fscanf(r, "%s\n", &str)
	fmt.Fscanf(r, "%s\n", &value)
	fmt.Fscanf(r, "%d\n", &k)
	hash = make([]uint64, len(str))

	fmt.Fprintf(os.Stdout, "%d\n", solve(str, k, len(str), value))
}


package main

import (
	"bufio"
	"fmt"
	"os"
)

var (
	base   = uint64(27)
	hash   = []uint64{}
	hashes = map[uint64]bool{}
)

func solve(s string, k int, n int, value string) int {
	count, hash := 0, uint64(0)
	var id byte

	for i := range s {
		count = 0
		hash = 0
		for j := i; j < n; j++ {
			id = s[j] - 'a'
			if value[id] == '0' {
				count++
			}
			if count <= k {
				hash = hash*base + uint64(s[j])
				hashes[hash] = true
			} else {
				break
			}
		}
	}

	return len(hashes)
}

func main() {
	r := bufio.NewReader(os.Stdin)
	var str, value string
	var k int

	fmt.Fscanf(r, "%s\n", &str)
	fmt.Fscanf(r, "%s\n", &value)
	fmt.Fscanf(r, "%d\n", &k)
	hash = make([]uint64, len(str))

	fmt.Fprintf(os.Stdout, "%d\n", solve(str, k, len(str), value))
}


package main

import (
	"bufio"
	"fmt"
	"os"
)

var (
	base      = uint64(127)
	maxN      = 1500 + 10
	powerBase = make([]uint64, maxN)
	hash      = make([]uint64, maxN)
	hashes    = map[uint64]bool{}
)

func solve(s string, k int, n int, value string) int {
	count := 0
	var id byte

	for i := range s {
		count = 0
		for j := i; j < n; j++ {
			id = s[j] - 'a'
			if value[id] == '0' {
				count++
				if count > k {
					break
				}
			}
			hashes[getHash(s[i:j+1])] = true
		}
	}

	return len(hashes)
}

func getHash(s string) uint64 {
	hash[0] = uint64(s[0])

	for i := 1; i < len(s); i++ {
		hash[i] = (hash[i-1]*base + uint64(s[i]))
	}

	return hash[len(s)-1]
}

func initPowerBase() {
	powerBase[0] = 1

	for i := 1; i < maxN; i++ {
		powerBase[i] = powerBase[i-1] * base
	}
}

func main() {
	r := bufio.NewReader(os.Stdin)
	var str, value string
	var k int

	fmt.Fscanf(r, "%s\n", &str)
	fmt.Fscanf(r, "%s\n", &value)
	fmt.Fscanf(r, "%d\n", &k)
	initPowerBase()

	fmt.Println(solve(str, k, len(str), value))
}


package main

import (
	"bufio"
	"fmt"
	"os"
)

var (
	base   = uint64(27)
	hash   = []uint64{}
	hashes = map[uint64]bool{}
)

func solve(s string, k int, n int, value string) int {
	count := 0
	var id byte

	for i := range s {
		count = 0
		for j := i; j < n; j++ {
			id = s[j] - 'a'
			if value[id] == '0' {
				count++
			}
			if count <= k {
				hashes[getHash(s[i:j+1])] = true
			} else {
				break
			}
		}
	}

	return len(hashes)
}

func getHash(s string) uint64 {
	hash[0] = uint64(s[0])

	for i := 1; i < len(s); i++ {
		hash[i] = (hash[i-1]*base + uint64(s[i]))
	}

	return hash[len(s)-1]
}

func main() {
	r := bufio.NewReader(os.Stdin)
	var str, value string
	var k int

	fmt.Fscanf(r, "%s\n", &str)
	fmt.Fscanf(r, "%s\n", &value)
	fmt.Fscanf(r, "%d\n", &k)
	hash = make([]uint64, len(str))

	fmt.Println(solve(str, k, len(str), value))
}