【字符串】最长不重复子串
参考资料:
http://www.ahathinking.com/archives/123.html
题目:
从一个字符串中找到一个连续子串,该子串中任何两个字符不能相同,求子串的最大长度并输出一条最长不重复子串
思路:
使用一个数组dp[i]记录到当前下标i的元素为止,最长的不重复子串长度。使用lastIndex记录上一个最长不重复子串的开始位置,
使用before表示当前元素重复出现的上一个位置,那么有如下的状态方程:
void lnrs_1(const char *s ,int size) { int visit[256]={0}; //记录上一次元素出现下标 memset(visit,-1,256*4); int *dp=new int[size]; //至下标为i的元素的最长不重复子串长度 memset(dp,0,size*4);
visit[s[0]]=0;
dp[0]=1; int endIndex=0; //最长不重复子串结束下标 int maxlen=0; //最长不重复子串长度 int lastIndex=0; //上一个不重复子串的开始位置 for(int i=1;i<size;i++) { if(visit[s[i]]==-1) //当前元素未重复出现 { dp[i]=dp[i-1]+1; visit[s[i]]=i; } else { if(lastIndex > visit[s[i]]) { dp[i]=dp[i-1]+1; } else { dp[i]=i-visit[s[i]]; lastIndex=visit[s[i]]+1; } visit[s[i]]=i; } if(dp[i] > maxlen) { maxlen=dp[i]; endIndex=i; } } cout<<"index:"<<endIndex-maxlen+1<<","<<endIndex<<endl; delete[] dp; }
改进版本:
考虑上上述实现,dp[i]表示下标为i的元素为止的最长重复子串,dp[i]的作用是更新maxlen(最长不重复子序列长度),可以使用curlen
表示至当前元素的最长不重复子串的长度,用于更新maxlen。
算法时间复杂度:O(n),空间复杂度O(1)
void lnrs(const char *s,int size) { int visit[256]; //记录当前元素上一次重复出现的位置 memset(visit,-1,256*4); visit[s[0]]=0; int endIndex=0; //最长不重复子串结尾位置 int maxLen=0; //最长不重复子串长度 int lastIndex=0; //上一个不重复子串的开始位置 int curlen=1; //至当前元素不重复子串的长度 for(int i=1;i<size;i++) { if(visit[s[i]]==-1) { curlen++; visit[s[i]]=i; } else { if(lastIndex > visit[s[i]]) { curlen++; } else { curlen=i-visit[s[i]]; lastIndex=visit[s[i]]+1; } visit[s[i]]=i; } if(curlen > maxLen) { maxLen=curlen; endIndex=i; } } cout<<"maxIndex:["<<endIndex-maxLen+1<<","<<endIndex<<"]"<<endl; }