之前对乔姆斯基范式不大了解。。(对的。。考试也没考好。。)。
乔姆斯基范式中,每个转移后的状态都只有两个大写字母或者一个小写字母。。。
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define maxn 110
class node
{
public:
int x,y;
}mmap[26][maxn];
int ans[26][26],dp[26][110][110],num[26];
int ss[maxn];
void init()
{
memset(ans,0,sizeof(ans));
memset(num,0,sizeof(num));
}
int search(int l,int r,int now)
{
if(l>r) return 0;
if(l==r)
{
if(ans[now][ss[l]]) return dp[now][l][l]=1;
return dp[now][l][l]=0;
}
if(dp[now][l][r]!=-1) return dp[now][l][r];
for(int i=l;i<r;i++)
{
for(int j=0;j<num[now];j++)
{
if(search(l,i,mmap[now][j].x)&&search(l+1,r,mmap[now][j].y)) return dp[now][l][r]=1;
}
}
return dp[now][l][r]=0;
}
int main()
{
int n,m;
char s[110];
while(scanf("%d",&n)!=EOF)
{
init();
while(n--)
{
scanf("%s",s);
int x=s[0]-'A';
for(int i=3;i<strlen(s);i++)
{
if(s[i]<='Z'&&s[i]>='A')
{
int j=s[i]-'A',k=s[i+1]-'A';
mmap[x][num[x]].x=j;
mmap[x][num[x]].y=k;
num[x]++;
i+=2;
}
else if(s[i]<='z'&&s[i]>='a')
{
int j=s[i]-'a';
ans[x][j]=1;
}
}
}
scanf("%d",&m);
while(m--)
{
memset(dp,-1,sizeof(dp));
scanf("%s",s);
int len=strlen(s);
for(int i=0;i<len;i++) ss[i]=s[i]-'a';
if(search(0,len-1,'S'-'A')) printf("yes\n");
else printf("no\n");
}
}
return 0;
}
//4
//S->AB
//A->AB|a
//B->BC|b
//C->CA|CC|c
//3
//ab
//ac
//bc