回复 32楼 吹水佬
跳过无需比较的位置原来叫suanday算法!
看来大家都青睐查表法,查表法优点是一次扫描定位,不需要倒查的那个循环,缺点是要花时间初始化表,如果是一个很短的字符串就有点大炮打蚊子了。查表效率体现在范围小、数据量大上,比如纯粹的英文应该只需要一个128个元素的表,而英汉混合的则需要65536个元素的表,前面几位范例都用了256个元素,个人感觉未做到最优。既然都青睐查表法,我也贴一个查表法的例子,希望能得到大神指点:
程序代码:
#include<stdio.h>
void maxlen(char* s, int *start, int *len)
{
//查表法查找字符串中最长不重复子串,返回子串起点在start,子串长度在len
int i,j,l,a[128]={0};
for(l=0; s[l]; l++); //首先获取原始字符串长度在l里
if(*start<0||*start>=l) *start=0; //起始位置未初始化的处理
for(i=*start,*len=0; i+*len<l;i++)
{
for(j=i;s[j]&&(a[s[j]]<=i||a[s[j]]==j+1);j++)
a[s[j]]=j+1; //记录下相应字符在字符串中的位置以备查表 ,弄清楚这个循环条件就明白了,所谓查表法就在这个循环条件里
if(j-i>*len)
{
*start=i;
*len=j-i;
}
if(a[s[j]]-1>i)i=a[s[j]]-1; //原来这一句就叫sunday算法,对出现重复字符跳过中间字符,不是逐个比较
//我在20楼指出的错误就在这里,跳过的位置错了,应跳至相同字符的前一个字符后面,我跳到后一个字符后面了。
}
}
void main()
{
//char str[80]="12345611718";
char str[80]="3212134532156";
int i,j,s,l,m,e;
//gets(str);
for(e=0; str[e]; e++);
for(i=0,m=0; i+m<=e; i++)
{
//输出所有最长子串"abcdab: abcd bcda cdab"
s=i;
maxlen(str,&s,&l);
if(m==0)m=l;
if(s>i)i=s;
if(l>=m)
{
for(j=0; j<l; j++)printf("%c",str[j+s]); //根据最长子串起点和长度输出该子串所有字符
printf("\n");
}
}
}
[此贴子已经被作者于2016-12-13 11:15编辑过]