uva310 - L--system

写这个题的代码的时候各种错啊,,

开始的时候想不到合适的算法,听人家说了思路后自己开始动手写,但是各种错。

想用二进制来表示字符串,例如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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值