写这个题的代码的时候各种错啊,,
开始的时候想不到合适的算法,听人家说了思路后自己开始动手写,但是各种错。
想用二进制来表示字符串,例如aaabb用00011来表示,免了写哈希判重
但是此时出现了问题就是aab与aaab与aaaab指相同,
如果三进制的话3^15又太大了,单单初始化就会TLE。
后来看一神人用最大值为2的二进制(当然这是不符合逻辑的),就是说用11122来代表aaabb
我这样改了一点点竟然过了,这是因为没有了0的二进制系统,只有1和2的编码,值是不会重复,因为不会存在10,现在2的存在是合理的,
这样下来新二进制中最小的数从1开始,1,2,11,12,21,22,111,112,121,122,211,212,221,222……
代码如下:
#include <cstdio>
#include <cstring>
#define MN 100003
char arigh[20], brigh[20], start[20], z[20], st[MN][20];
int ok, la, lb, ls, lz, vis[MN];
int try_to_insert(int cur)
{
int s = 0, len = strlen(st[cur]);
for(int i = 0; i < len; i++)
s = s * 2 + st[cur][i]-'a'+1;
if(!vis[s]) { vis[s] = 1; return 1; }
else return 0;
}
void solve(int lnow, int &front, char *A)
{
for(int cas = 0; cas < lnow-lz+1; cas++)
{
for(int i = cas, j = 0; j < lz; i++, j++)
st[front][j] = A[i];
st[front][lz] = '\0'; // 需要非常注意的地方
if(try_to_insert(front)) front++;
}
}
void bfs()
{
int rear = 0, front = 0;
memset(vis,0,sizeof(vis));
if(ls>=lz) solve(ls,front,start);
else { memcpy(st[front],start, sizeof(start)); if(try_to_insert(front))front++; }
while(rear<front)
{
char temp[200];
memset(temp,'\0',sizeof(temp));
int rearlen = strlen(st[rear]), templen;
if(strcmp(z,st[rear])==0) {ok = 1; break; }
for(int i = 0; i < rearlen; i++)
if(st[rear][i]=='a') strcat(temp,arigh);
else if(st[rear][i]=='b') strcat(temp,brigh);
templen = strlen(temp);
if(templen>=lz) solve(templen,front,temp);
else {memcpy(st[front],temp,sizeof(temp)); if(try_to_insert(front))front++; }
rear++;
}
}
int main ()
{
while(scanf("%s",arigh)!=EOF)
{
getchar();
scanf("%s",brigh); getchar();
scanf("%s",start); getchar();
scanf("%s",z); getchar();
la = strlen(arigh);
lb = strlen(brigh);
ls = strlen(start);
lz = strlen(z);
ok = 0;
if(lz==0) ok = 1;
else bfs();
printf("%s\n",ok?"YES":"NO");
}
return 0;
}