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编辑过]










不过感觉上要取出所有不重复的子串要比取只取其中一个最值的遍历次数要多很多,倒不如第一次先求最大长度,不保留子串,第二次再根据最值保留字符串。保留字符串用一个动态数组(可以用realloc来扩大空间)处理,每次输出长度为max的值行了。
其实我不但测试过你的代码,而且还改过你的代码。恕我编译器资源稀少,我手头暂时只有vc6,(迟点也许会更新)就是说函数加个地址vc是不支持的,改了加指针,然后在循环处设置了输出点测试了比较次数,效果我就不说了,自己知。单个字符输出来说可以说是我原版提供的最为理想,其次是队列(r版主的要改改我的编译器才能测试,这个先保留)。当然,如果我真的要改,第一次先求最大长度,然后第二次再输出所有最长子串,顶多效率降为原来的一半而已。不过你做求mathisfun那题还真不错,感觉那题型和你用的方法和这题有点共同之处。
,这个我慢慢弄是可以弄出来的,做这题题我的收获还是很大的,是时候该去结贴了~

看来我还是低估了这条题的价值量啊,原本我只是当一条难度稍大的常规题来做
……不过回帖的收获大大超出我的意料,早知我给个百分帖算了
。总之,算法原理大体相似,只是算法的花样较多而已,我对比了一下总多算法,无论儿子怎么不同,大都是出自同一个父亲的~不过,能尽量去优化代码还是很好的~