题目描述:
最长不重复子串(Longest No Repeat String,LNRS)就是从一个字符串中找到一个连续子串,该子串中任何两个字符都不能相同,且该子串的长度是最大的。
分析:
解法一:动态规划
动态规划就是用来解决这种最优化问题,关于字符串的很多有趣的问题如最长公共自序列,最长上升子序列等都可以用动态规划来解,这道题我的第一想法也是动态规划。
动态规划的核心在于寻找最优子结构,对于一个字符,如果他与他前面的最长不重复子串都没有相同的字符,那么他也可以加入这个子串中,构成一个新的子串。即对于字符数组a[],dp[i]表示以a[i]为结尾的最长不重复子串长度,dp[0] = 1,最后取dp中的最大值即可。代码如下:
1 #include <cstdio> 2 #include <cstdlib> 3 #include <string.h> 4 5 using namespace std; 6 char in[10001]; 7 8 int dp[10001]; 9 10 int LNRS_dp(char *in) 11 { 12 int i, j; 13 int len = strlen(in); 14 int last = 0; // 上一次最长子串的起始位置 15 int maxlen,maxindex; 16 maxlen = maxindex = 0; 17 18 dp[0] = 1; 19 for(i = 1; i < len; ++i) 20 { 21 for(j = i-1; j >= last; --j) // 遍历到上一次最长子串起始位置 22 { 23 if(in[j] == in[i]) 24 { 25 dp[i] = i - j; 26 last = j+1; // 更新last_start 27 break; 28 }else if(j == last) // 无重复 29 { 30 dp[i] = dp[i-1] + 1;//长度+1 31 } 32 } 33 if(dp[i] > maxlen) 34 { 35 maxlen = dp[i]; 36 } 37 } 38 return maxlen; 39 } 40 41 int main() 42 { 43 freopen("1530.in","r",stdin); 44 freopen("1530.out","w",stdout); 45 46 while(scanf("%s",in)!=EOF) 47 { 48 printf("%d\n",LNRS_dp(in)); 49 } 50 return 0; 51 }