写这个题的代码的时候各种错啊,,
开始的时候想不到合适的算法,听人家说了思路后自己开始动手写,但是各种错。
想用二进制来表示字符串,例如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; }