回 帖 发 新 帖 刷新版面

主题:关于80次编程比赛,最终代码在底楼,谢谢版主帮测

晚上我再重写代码,把要比较的字符串,开头有重复的字符先缩成一个字符再作比较,谢谢版主,晚上我再贴上来.

回想下线代的内容,对这题很有启发。

如果a中有一个字符比b的首字符大,那b串一定在该位置前插入,或者说,b串插入a的位置之前不能有比b首字符大的字符。。。
按这个思路考虑下去吧,你会发现这题居然是如此简单。
+++++++++++++++++++++++++++++++++++++++++++++++++
[color=FF00FF]代码已经重写过了,字典长度为4的测试文件完全通过,1楼的代码作废,当代码难以修改时,唯一的办法就是重写,请版主帮忙用100000长度的测试文件试试看,谢谢[/color]

回复列表 (共23个回复)

11 楼

#include <stdio.h>
#define MAXLEN 100000

//todo: 在此增加你所需要的函数或者变量或者头文件

void deal(char* a, char* b, char* c)
{
    // todo: 在此补充你的处理代码
    // 参数说明: a和b是输入的字符串,c要保存输出结果
    long i,j,k;
    long thead,twidth;
    long tnum_a,tnum_b;
    int flag,fend,fa,fb,fc;
    flag=fend=0;

    for(i=0;a[i] || flag && !fend;i++){
        if(!flag){
            if(a[i]>b[0]){break;}
            if(a[i]==b[0]){
                thead=i;twidth=tnum_a=tnum_b=1;flag=1;i++;
            }
        }
        if(flag==1){
cycle:      if(a[i] && a[i]==b[twidth] && a[i]<b[0]){
                twidth++;continue;
            }else if(!a[i])fend=1;
            j=fa=fb=fc=0;
            while(b[j%twidth]==b[twidth+j])j++;
            if(b[twidth+j]>b[j%twidth])fb=2;
            else if(b[twidth+j])fb=1;
            tnum_b+=j/twidth;

            j=0;
            while(b[j%twidth]==a[i+j])j++;
            if(a[i+j]>b[j%twidth])fa=2;
            else if(a[i+j])fa=1;
            tnum_a+=j/twidth;

            if(tnum_a>tnum_b)fc=2;
            else if(tnum_a<tnum_b)fc=1;

12 楼

//接上楼 
           i=thead+twidth*tnum_a;
            j=twidth*tnum_b;
            for(k=0;a[i+k]==b[k] && b[k]==b[j+k] && k<twidth;k++);
            if(a[i+k]==b[j+k]){
                if(a[i+k]>b[k]){break;}        //a=b>t
                else{                        //t>a=b
                    if(!fa){break;}
                    if(fc==2){i=thead;break;}
                    if(fc==0){
                        i+=k+1;
                        twidth*=tnum_a;
                        twidth+=k+1;
                        tnum_a=tnum_b=1;
                        goto cycle;
                    }
                    flag=0;
                }
            }else if(a[i+k]>b[j+k]){
                if(b[k]>a[i+k]){             //t>a>b
                    if(!fb || fc==1)flag=0;
                    else{i=thead;break;} 
                }else if(b[k]==a[i+k]){       //t=a>b
                    if(fa==2){
                        if(fb)i=thead;
                        break;
                    }else if(fb && (fa==0 || fc!=1)){
                        i=thead;break;
                    }else if(fb==0 && fa==0) break;
                    flag=0;
                }else if(b[k]>b[j+k]){        //a>t>b
                    if(!fb)break;
                    i=thead;break;
                }else if(b[k]==b[j+k]){       //a>t=b
                    if(fb==1)i=thead;
                    break;
                }else break;                  //a>b>t
            }else{
                if(b[k]>b[j+k]){             //t>b>a
                    if(fc==2 || fa==0){i=thead;break;}
                    flag=0;
                }else if(b[k]==b[j+k]){       //t=b>a
                    if(fb==1 &&(fc==2 || fa==0)){i=thead;break;}
                    flag=0;
                }else if(b[k]>a[i+k])flag=0;  //b>t>a
                else if(b[k]==a[i+k]){       //b>t=a
                    if(fa==2){break;}
                    flag=0;
                }else break;                        //b>a>t
            }
            i--;
        }
    }

    for(j=0;j<i;j++)   c[j]=a[j];
    for(j=0;b[j];j++)  c[i+j]=b[j];
    for(j+=i;a[i];i++) c[j++]=a[i];
    c[j]='\0';

    return;
}

char a[MAXLEN+1], b[MAXLEN+1], c[MAXLEN*2+1];
int main(void)
{
    while (scanf("%s%s", a, b)!=EOF)
    {
        deal(a, b, c);
        puts(c);
    }
    return 0;
}

13 楼

代码比较丑,只是个草稿,因为不知改了N次,才通过了5个数字6位长度的测试,烦请版主再次帮测,如果结果不出错,我再整理优化一遍代码,谢谢

14 楼

我用了大量的分支,就是为了减少循环比较的次数,把各种情况分得很细
我是把两个串看成波形来作比较的,事实上,当年信号处理原理俺根本没学懂,所以也没用到什么Z变换,傅里叶,频谱,只是按自己的思路来作波形的周期比较的,请各位大大不要喷我

15 楼

Name: "[color=Blue]Hawkxp[/color]" Problem ID "[color=Blue]135[/color]"
Submit Time: 2009/3/25-13:24

[color=red]G++: Compile Warning:
Line  In function `void deal(char*, char*, char*)':
Line 12: warning: 'thead' might be used uninitialized in this function
Line 12: warning: 'twidth' might be used uninitialized in this function
Line 13: warning: 'tnum_a' might be used uninitialized in this function
Line 13: warning: 'tnum_b' might be used uninitialized in this function
[/color]
Test  1:    [color=blue]Accepted[/color]    Time = 0 ms
Test  2:    [color=blue]Accepted[/color]    Time = 0 ms
Test  3:    [color=blue]Accepted[/color]    Time = 81 ms
Test  4:    [color=blue]Accepted[/color]    Time = 18 ms
Test  5:    [color=blue]Accepted[/color]    Time = 336 ms
Test  6:    [color=blue]Accepted[/color]    Time = 73 ms
--------------------------------
Problem ID     135
Test Result    [color=blue]Accepted[/color]
Total Time     508 ms
Total Memory   420 Kb / 2000 Kb
Code Length    3328 Bytes

恭喜,你是第一个pfan中能通过全部数据的人,我宣布,你就是第80次比赛的冠军,
第81次比赛将由Hawkxp主持

16 楼

楼主的思路很独特,所以如果楼主有时间的话,写一篇文章讲解一下你的算法思路给大家一起学习吧

17 楼

嗯,主持什么的还是版主来吧,我只是来玩玩,
简单说一下体会,当b串的波形是余弦波,其波峰的最高值和a串的波峰最高值相等的时候是比较麻烦的,如果两个串(a为从比较点开始的余弦波子串)的波形是以周期的形式开始且周期重合,那么分别跳过两串的周期,将两串出周期处的波形和周期的波形,三个波形进行比较,我那代码上注释的 t>a>b,T,就是周期,根据各种情况,决定B串是插入到a的周期循环部分之前还是之后.
其中,犹以b串的波形是余弦波被幅长更大的余弦波调制成的波形最为复杂,比如:
5454545315454545315454
开始判断出54 是一个周期,找到531的时候退出的54这个周期,但如果,a串的比较部分,54的周期次数和b串的周期次数相等,出周期的部分又和b相等为531的话,事实上,这是一个更大的周期,单个周期部分为:
545454531
需要按新的周期重新判断a,b串的周期情况和出周期的位置进行比较,事实上这里就会存在一个递归,为了不增加栈空间实现递归的效果,我用了一个 goto 语句(还被小令00笑了).
我明天要出差了,可能要一周左右,等我回来时再把整理优化后的代码和详细的算法思路拿出来吧,比赛请版主主持,我对那个二值化数字图形还原的题比较有兴趣,初步的想法是把图样取样后对波形二次求导,将重复的0合为一个,就将图形的转角情况全保留下来又出除了其它的信息,但从什么地方开始取样我还没能想出来,呵呵

18 楼

主持也就是你出一个题目让大家练习,然后你给出改进意见或者测试结果,当然后面这一步可以边比赛边进行或者等比赛结束后再一次完成(即结束前谁也不能看到对方提交的代码),你参考一下前几次比赛就知道了
出题还是解题,大家都是玩玩,玩的过程中学到东西,又何必介意呢。你就趁出差的时间想个好题目吧

19 楼

11,12楼的算法也还有完美,
最少
123  123
这组测试过不了,
应该输出112233
但程序输出的是112323
版主可以试一下.

20 楼

[quote]11,12楼的算法也还有完美,
最少
123  123
这组测试过不了,
应该输出112233
但程序输出的是112323
版主可以试一下.[/quote]
我试过了,是你把题目理解错

我来回复

您尚未登录,请登录后再回复。点此登录或注册