题意:在D0L这样一个系统中存在一个有限的集合(包含字母),一个P集合(字母的映射)和一个初始串。题目给定一个初始串,叫你判断是否能通过不断映射构成目标串或者包含该目标串的串。例如a->aa,b->bb,初始串为ab,目标串为aaabb,这样的话,初始串根据映射衍化(注意,扩展时必须同时采用两规则):ab(a->aa,b->bb)->aabb->aaaabbbb 这样就得到了含有目标串的串,输出YES。
思路:
1.BFS穷举所有状态。
2.保存每个状态。
3.存储所有和目标串长度相等的状态,利用HASH判重。
eg:
aa
bb
ab
aaaaabb
aaaaaaaaaabbbbb
aaaaaabbbbbbbbb
baaaababababaaa
abababbb
a
b
ab
ba
a
b
ab
ab
a
b
aaab
ba
YES
NO
NO
YES
NO
#include<stdio.h>
#include<string.h>
#define MAXSIZE 1000003
char aRight[20],bRight[20],start[20],dest[20];
char state[MAXSIZE][20];
int len,flag;
int hash[MAXSIZE],aimValue;
int getValue(int n)
{
int i,v=0;
for(i=0;i<strlen(state[n]);i++)
{
v=v*2+state[n][i]-'a'+1;
}
return v;
}
void BFS()
{
int front=0,rear=0,i,j,k,tag=0;
char current[20],temp[200];
memset(current,0,sizeof(current));
memset(temp,0,sizeof(temp));
memset(hash,0,sizeof(hash));
aimValue=0;
for(i=0;i<strlen(dest);i++)
{
aimValue=aimValue*2+dest[i]-'a'+1;
}
if(strstr(start,dest)!=NULL)
{
flag=1;
return;
}
//穷举存入初始状态
for(i=0;i<strlen(start);i++)
{
tag=0;
for(j=i,k=0;j<strlen(start)&&k<len;j++,k++)
{
state[rear][k]=start[j];
}
state[rear][k]='\0';
tag=getValue(rear);
if(!hash[tag])
{
hash[tag]=1;
rear++;
}
}
while(front<rear)
{
if(hash[aimValue]){flag=1;return;}
strcpy(current,state[front]);
memset(temp,0,sizeof(temp));
//穷举扩展
for(i=0;i<strlen(current);i++)
{
if(current[i]=='a')
{
strcat(temp,aRight);
}
else if(current[i]=='b')
{
strcat(temp,bRight);
}
}
//hash判重,存储
for(i=0;i<strlen(temp);i++)
{
for(j=i,k=0;j<strlen(temp)&&k<len;j++,k++)
{
state[rear][k]=temp[j];
}
state[rear][k]='\0';
tag=getValue(rear);
if(!hash[tag])
{
hash[tag]=1;
rear++;
}
}
front++;
}
}
int main()
{
while(scanf("%s",aRight)!=EOF)
{
scanf("%s%s%s",bRight,start,dest);
flag=0;
len=strlen(dest);
BFS();
if(flag||dest[0]=='\0')printf("YES\n");
else printf("NO\n");
}
return 0;
}