#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <map>
using namespace std;
struct Node {
map<char, int> children;
int failure;
int output; // Index of the virus (or -1 if no output)
Node() : failure(0), output(-1) {}
};
int main() {
int numRows, numCols, numViruses;
cin >> numRows >> numCols >> numViruses;
vector<vector<char>> board(numRows, vector<char>(numCols));
for (int row = 0; row < numRows; ++row) {
for (int col = 0; col < numCols; ++col) {
cin >> board[row][col];
}
}
vector<string> viruses(numViruses);
cin.ignore();
for (int i = 0; i < numViruses; ++i) {
getline(cin, viruses[i]);
}
// 1. Build the Trie
vector<Node> trie;
trie.push_back(Node()); // Root node
int nodeCount = 1;
for (int i = 0; i < numViruses; ++i) {
int currentNode = 0;
for (char c : viruses[i]) {
if (trie[currentNode].children.find(c) == trie[currentNode].children.end()) {
trie.push_back(Node());
trie[currentNode].children[c] = nodeCount++;
}
currentNode = trie[currentNode].children[c];
}
trie[currentNode].output = i; // Mark the end of the virus
}
// 2. Build Failure Links (BFS)
queue<int> qNodes;
for (auto const& [character, childNode] : trie[0].children) {
qNodes.push(childNode);
}
while (!qNodes.empty()) {
int currentNode = qNodes.front();
qNodes.pop();
for (auto const& [character, childNode] : trie[currentNode].children) {
int nextNode = childNode;
int failureNode = trie[currentNode].failure;
while (trie[failureNode].children.find(character) == trie[failureNode].children.end() && failureNode != 0) {
failureNode = trie[failureNode].failure;
}
if (trie[failureNode].children.find(character) != trie[failureNode].children.end()) {
trie[nextNode].failure = trie[failureNode].children[character];
}
if (trie[nextNode].output == -1) {
trie[nextNode].output = trie[trie[nextNode].failure].output;
}
qNodes.push(nextNode);
}
}
// 3. Search in the Board
string result(numViruses, '0');
// Search horizontally
for (int row = 0; row < numRows; ++row) {
int currentNode = 0;
for (int col = 0; col < numCols; ++col) {
char c = board[row][col];
while (trie[currentNode].children.find(c) == trie[currentNode].children.end() && currentNode != 0) {
currentNode = trie[currentNode].failure;
}
if (trie[currentNode].children.find(c) != trie[currentNode].children.end()) {
currentNode = trie[currentNode].children[c];
}
if (trie[currentNode].output != -1) {
result[trie[currentNode].output] = '1';
}
}
}
// Search vertically
for (int col = 0; col < numCols; ++col) {
int currentNode = 0;
for (int row = 0; row < numRows; ++row) {
char c = board[row][col];
while (trie[currentNode].children.find(c) == trie[currentNode].children.end() && currentNode != 0) {
currentNode = trie[currentNode].failure;
}
if (trie[currentNode].children.find(c) != trie[currentNode].children.end()) {
currentNode = trie[currentNode].children[c];
}
if (trie[currentNode].output != -1) {
result[trie[currentNode].output] = '1';
}
}
}
cout << result << endl;
return 0;
}