Problem:
String Search

Determine whether a text T includes a pattern P. Your program should answer for given queries consisting of P_i.

Input

In the first line, a text T is given. In the second line, an integer Q denoting the number of queries is given. In the following Q lines, the patterns P_i are given respectively.

Output

For each question, print 1 if the text includes P_i, or print 0 otherwise.

Constraints

1 ≤ length of T ≤ 1000000

1 ≤ length of P_i ≤ 1000

1 ≤ Q ≤ 10000

The input consists of alphabetical characters and digits

Sample Input 1

aabaaa
4
aa
ba
bb
xyz

Sample Output 1

1
1
0
0

Solution in C# (judge verdict: Accepted)

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

namespace ConsoleApplication1
{
    class SuffixArray
    {
        readonly int SIZE = byte.MaxValue * byte.MaxValue;
        readonly int LIMIT = 16;
        readonly string Text;

        byte[] Data;
        int[] index, rank;
        int size;

        public SuffixArray(string text)
        {
            Text = text;

            MakeSuffixArray(text);
        }

        private int[] MakeSuffixArray(byte[] data)
        {
            size = data.Length;
            Data = new byte[size + 1];
            Array.Copy(data, Data, size);

            index = new int[size];
            rank = new int[size];

            SuffixSort();

            return index;
        }

        private int[] MakeSuffixArray(string source)
        {
            byte[] ret = new byte[source.Length];

            for (int i = 0; i < source.Length; i++)
            {
                ret[i] = (byte)source[i];
            }
            return MakeSuffixArray(ret);
        }

        private int GetRank(int i) { return i < size ? rank[i] : -1; }

        private void SuffixSort()
        {
            int[] count = new int[SIZE];
            int[] sum = new int[SIZE + 1];

            for (int i = 0; i < size; i++)
            {
                count[(Data[i] << 8) + Data[i + 1]]++;
            }

            for (int i = 1; i < SIZE + 1; i++)
            {
                sum[i] = count[i - 1] + sum[i - 1];
            }

            for (int i = 1; i < SIZE; i++)
            {
                count[i] += count[i - 1];
            }

            int c;

            for (int i = size - 1; i > -1; i--)
            {
                c = (Data[i] << 8) + Data[i + 1];
                count[c]--;
                index[count[c]] = i;
                rank[i] = sum[c + 1] - 1;
            }

            for (int n = 2; n < size; n <<= 1)
            {
                int low = 0;
                bool flag = true;

                while (low < size)
                {
                    int temp = low;

                    while (temp < size && index[temp] < 0) temp -= index[temp];

                    if (low < temp)
                    {
                        index[low] = -(temp - low);
                        low = temp;
                    }

                    if (low < size)
                    {
                        int high = rank[index[low]];
                        MqSort(low, high, n);
                        low = high + 1;
                        flag = false;
                    }
                }

                if (flag) break;
            }

            for (int i = 0; i < size; i++) index[rank[i]] = i;
        }

        private void MqSort(int low, int high, int n)
        {
            if (high - low <= LIMIT)
            {
                InsertSort(low, high, n);
                return;
            }

            int p = SelectPivot(low, high, n);

            int i, j, m1, m2;
            i = m1 = low;
            j = m2 = high;

            while (true)
            {
                int k = 0;

                while (i <= j)
                {
                    k = GetRank(index[i] + n) - p;

                    if (k > 0) break;

                    if (k == 0)
                    {
                        Swap(i, m1);
                        m1++;
                    }
                    i++;
                }

                while (i <= j)
                {
                    k = GetRank(index[j] + n) - p;

                    if (k < 0) break;

                    if (k == 0)
                    {
                        Swap(j, m2);
                        m2--;
                    }
                    j--;
                }

                if (i > j) break;

                Swap(i, j);
                i++; j--;
            }

            int min = Math.Min(m1 - low, i - m1);
            for (int k = 0; k < min; k++) Swap(low + k, j - k);
            m1 = low + (i - m1);

            min = Math.Min(high - m2, m2 - j);
            for (int k = 0; k < min; k++) Swap(high - k, i + k);
            m2 = high - (m2 - j) + 1;

            if (low <= m1 - 1) MqSort(low, m1 - 1, n);

            if (m2 > m1)
            {
                if (m2 - m1 == 1)
                {
                    rank[index[m1]] = m1;
                    index[m1] = -1;
                }
                else
                {
                    int r = m2 - 1;
                    for (int l = m1; l < m2; l++) rank[index[l]] = r;
                }
            }

            if (m2 <= high) MqSort(m2, high, n);
        }

        int SelectPivot(int low, int high, int n)
        {
            int m = (high - low) / 4;
            int a = GetRank(index[low + m] + n),
                b = GetRank(index[low + m * 2] + n),
                c = GetRank(index[low + m * 3] + n);
            if (a > b)
            {
                a ^= b;
                b ^= a;
                a ^= b;
            }
            if (b > c)
            {
                b = c;
                if (a > b) b = a;
            }
            return b;
        }

        private void Swap(int i, int j)
        {
            int t = index[i];
            index[i] = index[j];
            index[j] = t;
        }

        int Compare(int x, int y, int n)
        {
            int m = size - Math.Max(x, y);
            int r;

            for (int i = n; i < m; i += n)
            {
                r = rank[x + i] - rank[y + i];
                if (r != 0) return r;
            }
            return y - x;
        }

        private void InsertSort(int low, int high, int n)
        {
            high++;

            for (int i = low + 1; i < high; i++)
            {
                int t = index[i];
                int j = i - 1;

                while (j >= low && Compare(t, index[j], n) < 0)
                {
                    index[j + 1] = index[j];
                    j--;
                }
                index[j + 1] = t;
            }

            for (int i = low; i < high; i++)
            {
                rank[index[i]] = i;
                index[i] = -1;
            }
        }

        public void PrintSuffixArray()
        {
            for (int i = 0; i < index.Length; i++)
            {
                string g = GetString(i, size);
                Console.WriteLine(g);
            }
        }

        string GetString(int idx, int n)
        {
            int s = index[idx];
            int e = Math.Min(Data.Length, s + n);

            StringBuilder sb = new StringBuilder();

            if (s == 0)
            {
                for (int i = s; i < e; i++) sb.Append((char)Data[i]);
            }
            else
            {
                for (int i = s; i < e - 1; i++) sb.Append((char)Data[i]);
            }

            return sb.ToString();
        }

        public bool Contains(string pattern)
        {
            int l = 0, r = size;

            while (l < r)
            {
                int m = (l + r) / 2;

                string subStr = (index[m] + pattern.Length > size) ?
                    Text.Substring(index[m]) :
                    Text.Substring(index[m], pattern.Length);

                int comp = subStr.CompareTo(pattern);
                if (comp == 0) return true;

                if (comp < 0) l = m + 1;
                else r = m;
            }
            return false;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            string T = Console.ReadLine();

            SuffixArray SA = new SuffixArray(T);
            StringBuilder sb = new StringBuilder();

            int Q = int.Parse(Console.ReadLine());

            for (int i = 0; i < Q; i++)
            {
                string P = Console.ReadLine();

                sb.AppendLine(SA.Contains(P) ? "1" : "0");
            }
            Console.Write(sb);
        }
    }
}