#include<iostream>
using namespace std;
int main()
{
int n,m; //n行满足乔姆斯基范式的文法描述, m行待测字符串
while(cin>>n)
{
string *cfg; //CFG文法描述
cfg=new string[n];
for(int i=0;i<n;i++)
cin>>cfg[i]; //输入CFG文法
cin>>m; //输入待测字符串数量
string *str; //待测字符串
str=new string[m];
for(int i=0;i<m;i++)
cin>>str[i]; //输入待测字符串
int *lstr; //待测字符串的长度
lstr=new int[m];
for(int i=0;i<m;i++)
lstr[i]=str[i].length();
string ***table; //定义表格
table=new string**[m];
for(int i=0;i<m;i++)
table[i]=new string*[lstr[i]];
for(int i=0;i<m;i++)
for(int j=0;j<lstr[i];j++)
table[i][j]=new string[lstr[i]];
//找出所有A->b型规则
string Ab[100];
int num=0;
for(int i=0;i<n;i++)
{
for(int k=3;k<cfg[i].length();k++)
{
if(cfg[i][k]>96 && cfg[i][k]<123)
{
Ab[num]+=cfg[i][0];
Ab[num]+=cfg[i][k];
num++;
}
}
}
//找出所有A->BC型规则
string ABC[100];
int num2=0;
for(int i=0;i<n;i++)
{
for(int k=3;k<cfg[i].length();k++)
{
if(cfg[i][k]<91)
{
ABC[num2]+=cfg[i][0];
ABC[num2]+=cfg[i][k];
ABC[num2]+=cfg[i][k+1];
k++;
num2++;
}
}
}
//考察每一个长为1的子串
for(int i=0;i<m;i++)
{
for(int j=0;j<lstr[i];j++) //考察每一个长为1的子串
{
for(int k=0;k<num;k++)
{
if(str[i][j]==Ab[k][1]) //考察CFG文法的每一个字符
table[i][j][j]=Ab[k][0];
}
}
}
//考察l长度的子串
for(int i=0;i<m;i++)
{
for(int l=2;l<=lstr[i];l++) //l是子串的长度
{
for(int p=0;p<lstr[i]-l+1;p++) //p是子串的起始位置
{
int j=p+l-1; //j是子串的结束位置
for(int k=p;k<j;k++) //k是分裂的位置 k<=j-1 ->k<j
{
for(int q=0;q<num2;q++)
{
if(table[i][p][k].find(ABC[q][1],0)!=string::npos && table[i][k+1][j].find(ABC[q][2],0)!=string::npos)
{
table[i][p][j]+=ABC[q][0];
}
}
}
}
}
}
//检查起始变元是否在table[0][n]中
for(int i=0;i<m;i++)
{
int flag=0;
if(table[i][0][lstr[i]-1].find(cfg[0][0],0)!=string::npos)
flag=1;
if(flag==1)
cout<<"yes"<<endl;
else
cout<<"no"<<endl;
}
//释放数组
delete []cfg;
delete []str;
//释放表格
for(int i=0;i<m;i++)
for(int j=0;j<lstr[i];j++)
delete []table[i][j];
for(int i=0;i<m;i++)
delete []table[i];
delete []table;
}
return 0;
}
|