标题:QA输出最长不重复子串(附加思维流程图)
取消只看楼主
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
结帖率:99.25%
已结贴  问题点数:20 回复次数:8 
QA输出最长不重复子串(附加思维流程图)


弄了一个通宵,终于把代码抖出来了,感觉这个写得还是不错的。
在解决编程应用题的时候,一开始难免会遇到无从下手,找不到思路的情况,于是我就在写程序之前把程序框架以及思维流程模拟出来,个人觉得这种写流程图解编程应用题的方法不错,于是把一个样板拿出来给大家参考一下。

流程图就像起房子的图纸,写程序按照该流程图来写的。特别是遇到逻辑理解上档次的时候,写流程图能增强对程序的理解能力,而且找出错误的位置及其性质也会相对容易一些。

程序代码:
/*题目:找出最长没有重复字符的子串*/

/*
    #思路:

    1-建立ACSII表判断重复字符
    2-记录本串长度-两个重复字符出现的位置,以及第一个字符出现的位置
    3-下次判断以第一个字符的下一个字符开始,判断位置从子串端的下一个字符开始
    4-如果出现子串较长,则更记录最长新子串的位置
    5-执行上述操作用选择法出最长字符,以及最长子串的位置,读出数据

    #需要用到的主要变量:

    1-ASSII表ASS[256]
    2-起始指针p1(值为子串左端位置)
    3-检索指针p2(值为子串右端位置)
    4-记录指针p3(值为子串出现重复字符的左端位置)
    5-记录最长子串起始位置的指针p_Max
    6-记录子串长度变量L
    7-记录最长子串长度L_Max
    

    #需要用到的函数

    1-char *fun(char *p1,char **p2)
    说明:-记录最长子串。

    返回值:
          (条件分歧)如果检索指针p2没有走到尾部
    返回子串出现重复字符左端的位置p1
    (如果检索指针p2走到尾部)
          就返回起始位置,依然为p1
    返回后用l=p2-p3记录子串长度

    返回后把L_max与原L比较,如果L_max>L则记录最长子串指针p_Max=p1;

    #结构

    循环结构(循环执行条件: strlen(p1)>L_Max)/*就是说当p1指向剩余字符串长度大于所求子串最大值
    {
             (注意:)开头要用p3=p1;\\目的是保留本次字执行符串操作的起始位置
             尾部要加p1++,p2++;意思是移动指针从检索出重复字符的到下一个位置开始检验
    }*/

#include<stdio.h>
#include<string.h>

char *fun(char *p1,char **p2)
{
    static int ASS[256]={0};

    for (;++ASS[**p2]!=2&&**p2;++*p2);

    if (!**p2)
        return p1;

    for (--ASS[*p1];*p1!=**p2;--ASS[*p1])
          ++p1;

    return p1;
}

int main()
{
    char s[80];
    char *p1,*p2,*p3,*p_Max;

    int L,L_Max;

    L=L_Max=0;

    p_Max=p1=p2=p3=s;

    gets(s);

    while (strlen(p1)>L_Max)
    {
        p3=p1;    

        p1=fun(p1,&p2);

        L=p2-p3;

        if (L>L_Max)
        {
            L_Max=L;
            p_Max=p3;
        }

        p1++;
        p2++;
    }

    printf("%.*s\n",L_Max,p_Max);

    return 0;
}




[此贴子已经被作者于2016-12-9 03:54编辑过]

搜索更多相关主题的帖子: 能力 而且 应用题 流程图 
2016-12-09 03:52
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
得分:0 
回复 4楼 吹水佬
我设想一个空间足够大的动态数组用来保存所有最长子串,但由于最长子串长度可能会发生变化,当最长子串长度发生变化时,缓冲区里面的子串也要跟着更新,而且容易造成空间浪费,不太好做,我尝试过了,不好实现;又设想先求最长子串长度,在此前提下再选出所有子串,但感觉在第一次基础上还要重复遍历一遍字符串,效率不高。或许是我未够火候,还请高手指教。

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-10 21:39
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
得分:0 
回复 12楼 xzlxzlxzl
可以可以不过感觉上要取出所有不重复的子串要比取只取其中一个最值的遍历次数要多很多,倒不如第一次先求最大长度,不保留子串,第二次再根据最值保留字符串。保留字符串用一个动态数组(可以用realloc来扩大空间)处理,每次输出长度为max的值行了。


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-11 15:10
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
得分:0 
回复 18楼 xzlxzlxzl
我笑了 其实我不但测试过你的代码,而且还改过你的代码。恕我编译器资源稀少,我手头暂时只有vc6,(迟点也许会更新)就是说函数加个地址vc是不支持的,改了加指针,然后在循环处设置了输出点测试了比较次数,效果我就不说了,自己知。单个字符输出来说可以说是我原版提供的最为理想,其次是队列(r版主的要改改我的编译器才能测试,这个先保留)。当然,如果我真的要改,第一次先求最大长度,然后第二次再输出所有最长子串,顶多效率降为原来的一半而已。不过你做求mathisfun那题还真不错,感觉那题型和你用的方法和这题有点共同之处。

[此贴子已经被作者于2016-12-11 19:13编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-11 19:11
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
得分:0 
回复 20楼 xzlxzlxzl
其实我也不知道自己测试的代码可不可靠,我只是在每个循环初加入输出一个字符,然后统计输出字符的数量,但运用库函数耗时用这法是无法测试出来的。至于精确耗间,还是要用time.h头文件来测试,不过对于小型字符串来说,用time.h相差不会太明显,我也没用time.h测试了,初步估计少于1毫秒。这完全可以自己简单测试执行效率~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-11 19:54
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
得分:0 
回复 9楼 吹水佬
多谢指点,这个我慢慢弄是可以弄出来的,做这题题我的收获还是很大的,是时候该去结贴了~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-12 13:16
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
得分:0 
虽然已经结贴,但我还是感到意犹未尽~对于输出所有最长的不重复子串,经过一段时间酝酿算法后,我发现了还是在原贴的基础上实现的~拿出来show一下~~~~

由于最长子串的长度为定值,所以……realloc就是管用!!!

程序代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define Input_Max 10

char *fun(char *p1,char **p2)
{
    static int ASS[256]={0};

    for (;++ASS[**p2]!=2&&**p2;++*p2);

    if (!**p2)
        return p1;

    for (--ASS[*p1];*p1!=**p2;--ASS[*p1])
          ++p1;

    return p1;
}

int main()
{
    char *s=(char *)malloc(Input_Max);
    char *p1,*p2,*p3;
    char *p_Max=NULL;

    int L,L_Max;
    int n=1;

    L=L_Max=0;

    p1=p2=p3=s;

    for (;(*p1=getchar())!='\n';p1++)
        if (p1-s>=n*Input_Max-1)
            realloc(s,++n*Input_Max);


    *p1='\0';
    p1=s;

    while ((int)strlen(p1)>=L_Max)
    {
        p3=p1;    

        p1=fun(p1,&p2);

        L=p2-p3;

        if (L>L_Max)
        {
            n=1;
            free(p_Max);
            p_Max=(char *)malloc(sizeof(char));
        }

        if (L>=L_Max)
        {
            L_Max=L;

            realloc(p_Max,n*L_Max*sizeof(char));
            memcpy(p_Max+(n-1)*L_Max,p3,L_Max*sizeof(char));

            ++n;
        }

        ++p1;
        ++p2;
    }

    for (p1=p_Max;n-->1&&s[0];p_Max+=L_Max)
        printf("%.*s\n",L_Max,p_Max);

    free(p1);
    free(s);

    return 0;
}

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-13 03:19
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
得分:0 
参考25楼的,又改进了一下算法,不用memcpy,直接用动态指针数组标记所有最长子串的起点~//突然发现自己越来越追求程序的执行效率

程序代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define Input_Max 10

char *fun(char *p1,char **p2)
{
    static int ASS[256]={0};

    for (;++ASS[**p2]!=2&&**p2;++*p2);

    if (!**p2)
        return p1;

    for (--ASS[*p1];*p1!=**p2;--ASS[*p1])
          ++p1;

    return p1;
}

int main()
{
    char *s=(char *)malloc(Input_Max);
    char *p1,*p2,*p3;
    char **p_Max=NULL;

    int L,L_Max;
    int n=1,count=0;

    L=L_Max=0;

    p1=p2=p3=s;

    for (;(*p1=getchar())!='\n';p1++)
        if (p1-s>=n*Input_Max-1)
            realloc(s,++n*Input_Max);


    *p1='\0';
    p1=s;

    while ((int)strlen(p1)>=L_Max)
    {
        p3=p1;    

        p1=fun(p1,&p2);

        L=p2-p3;

        if (L>L_Max)
        {
            n=1;
            free(p_Max);
            p_Max=(char **)malloc(sizeof(char*));
        }

        if (L>=L_Max)
        {
            L_Max=L;

            realloc(p_Max,n*sizeof(char*));
            p_Max[n-1]=p3;

            ++n;
        }

        ++p1;
        ++p2;
    }

    for (;count<(n-1)&&s[0];count++)
        printf("%.*s\n",L_Max,p_Max[count]);

    free(p_Max);
    free(s);

    return 0;
}


[此贴子已经被作者于2016-12-13 04:07编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-13 04:02
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
得分:0 
大家辛苦了,真是感谢大神们的鼎力相助啊看来我还是低估了这条题的价值量啊,原本我只是当一条难度稍大的常规题来做……不过回帖的收获大大超出我的意料,早知我给个百分帖算了。总之,算法原理大体相似,只是算法的花样较多而已,我对比了一下总多算法,无论儿子怎么不同,大都是出自同一个父亲的~不过,能尽量去优化代码还是很好的~        学习了

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-13 13:00



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-472169-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.545786 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved