最长不反复子串就是从一个字符串中找到一个连续子串,该子串中不论什么两个字符都不能同样,且该子串的长度是最大的。
输入:
输入包括多个測试用例,每组測试用例输入一行由小写英文字符a,b,c...x,y,z组成的字符串,字符串的长度不大于10000。
输出:
对于每组測试用例,输出最大长度的不反复子串长度。
例子输入:
absd
abba
abdffd
例子输出:
4
2
4
来源:
阿尔卡特2013年实习生招聘笔试题
分析:
这个属于贪心算法,最长不反复子串,思路是当出现反复的字符,则从開始扫描的字符后面的一个字符继续扫描,假设不出现反复的则将母串的字符加到子串中。
/* 1仅仅包含小写字母 子串最长为26 max==26 break; 2须要回溯 */ #include<stdio.h> #include<stdlib.h> #include<string.h> int main() { char str[10000],subStr[26];//0-25 最长是26个字符串 int max,i,j,strLength,subStrLength,index; //max:当前最大不反复子串长度,max最大仅仅能使26,由于不反复的小写字母最多就26个 //index:游标,记录子串開始扫描的字符的位置 while(~scanf("%s",str)) { max=0;//最大不反复子串长度初始化为0 strLength=strlen(str);//母串长度 subStrLength=0;//子串长度初始化为0 //线性扫描。 //1出现反复回到index后面的位置,继续扫描。 //2没有反复,则将str[i]增加到subStr中 for(i=0; i<strLength; i++) { //假设子串为空 if(subStrLength==0) { index=i;//index:记录母串扫描的開始位置 subStr[subStrLength++]=str[i]; continue; } //线性扫描subStr,是否与str[i]反复 for(j=0;j <subStrLength; j++) { //当有反复的序列的时候直接退出 if(str[i]==subStr[j]) { if(max<subStrLength) { max=subStrLength; } //反复即清空数组 memset(subStr,0,sizeof(char)*subStrLength); subStrLength=0;//恢复子串长度为0 i=index;//i回到index的位置,当i++时,自己主动跳到扫描字符的后面位置 break; } } //扫描后发现没有反复 if(subStrLength!=0&&j==subStrLength) { //没有反复的序列,子串长度变长,增加不反复的字符 subStr[subStrLength++]=str[i]; if(max<subStrLength) { max=subStrLength; } } //最大长度仅仅能是26,当max==26时就不继续进行扫描了 if(26==max) break; } printf("%d\n",max); memset(str,0,sizeof(char)*strLength);//清空str memset(subStr,0,sizeof(char)*subStrLength);//清空subStr } return 0; }