请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
定义函数f(i)表示以第i个字符为结尾的不包含重复字符的子字符串的最大长度。下面以第i个字符之前有没有出现过重复字符分为两种情况讨论。
如果第i个字符之前没有出现过重复字符,即f=f(i-1)+1。在字串“dhabcacfh”
中,显然f(0)=1,计算下标为1的h之前没有出现过h,所以f(1)=f(0)+1=2。最长的不包含重复字符的子字符串为“dh”。
如果第i个字符之前出现过重复字符,就要计算第i个字符和它上次出现在字符串中得位置的距离d。分两种情况:
(1)如果d小于或等于f(i-1),此时第i个字符上次出现在f(i-1)对应的最长子字符串中,因此f(i)=d;
(2)如果d大于f(i-1),此时第i个字符上次出现在f(i-1)对应的最长子字符串之前,f=f(i-1)+1成立依然。以字符串“dhabcacfh”为例,在最后一个字符h之前以f为结尾的最长不包含重复字符的字符串是"acf",即f(7)=3。最后一个字符h在字符串“arabcacfr”中下标为1的位置出现过,即d=7>f(7),说明上一个字符h不在f(7)对应的最长子字符串"acf"中,因此f(8)=f(7)+1=4。即以h为结尾的最长不包含重复字符的字符串是"acfh"。
代码如下:
#include<stdio.h>
#include<stdlib.h>
int longestStrNoRepetition(char *str, int length)
{
int curLength = 0;
int maxLength = 0;
int *position = (int *)malloc(26 * sizeof(int));
//下标初始化为-1表示i对应的元素还没在str中出现过
for (int i = 0; i < 26; ++i)
{
position[i] = -1;
}
for (int i = 0; i < length; i++)
{
int preIndex = position[str[i] - 'a'];
//第i个字符之前没出现过重复字符
if (preIndex<0 || i - preIndex>curLength)
++curLength;
else
{
//第i个字符之前出现过重复字符
if (curLength>maxLength)
maxLength = curLength;
curLength = i - preIndex;
}
//标记i出现在str字符串中的下标
position[str[i] - 'a'] = i;
}
if (curLength>maxLength)
maxLength = curLength;
free(position);
position = NULL;
return curLength;
}