字符串中的无重复最长子串

题目 

给定ascii字符串 s ,找出最长不重复子串。 要求时间复杂度为O(n)。
 例:      s = "abcdadefg"  => max_sub_uniq_str = "adefg"

分析

方法1

设置两个索引: 当前子串开始索引 cur_begin,  和当前字符索引 index, 针对当前字符s[index],

查找区间 【 s[cur_begin], s[index] )是否存在字符s[index]字符。

如果不存在, index++,继续一个字符;

如果存在需要回溯处理:

  m1: cur_begin++, index = cur_begin + 1;  这样处理肯定会浪费了以前的比较处理结果;

  m2 :  cur_begin 从重复字符下一个位置开始,比如 s = "Abcbagh" , 当cur_begin = 0, index = 3时

        s[1] = s[3] = b.  1为重复字符的索引,cur_begin = 1 + 1 = 2 开始。

无论m1 还是 m2, 时间复杂度肯定不是O(n)。

方法2:

由于是ascii字符串, 那么字符串中包含的不重复字符最多有256个。

使用一个包含256个元素数组marks,记录各个字符出现在字符串中的索引。marks[x] 的值大于当前子串的开始索引,

那么说明 子串 【 s[cur_begin], s[index])中包含 s[index]字符,此时, cur_begin = marks[s[index]] + 1,

该方法不需要回溯,时间复杂度为O(n),空间复杂度为 为常数。

代码

 1 #include <stdio.h>
 2 #include <string.h>
 3 void print(const char *s, int start, int last) {
 4     int i = start;
 5     printf("sub_str s = %d e = %d :", start, last);
 6     if(i == -1)
 7         return
 8     for( ; i <= last; i++) {
 9             printf("%c", s[i]);
10     }
11     printf("\n\n");
12 }
13  
14 int find_max_uniq_sub_str(const char *s, int *start, int *last) {
15     int max_begin = 0; // max sub str start index
16     int max_end   = 0; // max sub str end index
17     int cur_begin = 0; // 当前子串的开始索引
18     int marks[256] = { -1 };
19     int index = 0;
20     int temp_idx = 0;
21     int exist_dup = 0;
22     if(s == NULL || start == NULL || last == NULL)
23         return -1;
24     // -1 every byte is -1
25     memset(flags, -1, sizeof(flags));
26     while(s[index]) {
27         temp_idx = s[index]; 
28         if( marks[ temp_idx ] >= cur_begin ) { 
29         // [cur_begin, index] 中, s[flags[ temp_idx ] = s[index]
30                 exist_dup = 1;
31                 if( (index - cur_begin) > (max_end + 1 - max_begin) ) { 
32                 // [cur_begin, index) 与 [begin, end] 区间的大小
33                         max_begin = cur_begin;
34                         max_end   = index - 1;
35                 }
36                 print(s, max_begin, max_end);
37                 cur_begin = marks[ temp_idx ] + 1; // 更新当前子串的起始位置
38         }
39         flags[ temp_idx ] = index++;
40     }
41     if(!exist_dup) { // 无重复
42         max_end = index-1; 
43     }
44     *start = max_begin;
45     *last  = max_end;
46     return 0;
47  }
48  int main(int argc, const char*argv[]) {
49     int start = -1;
50     int last  = -1;
51     printf("argv[1] = %s\n", argv[1]);
52     find_max_uniq_sub_str(argv[1], &start, &last);
53     print(argv[1], start, last);
54     return 0;
55  }

 

posted @ 2016-02-19 10:59  mizhouli  阅读(86)  评论(0)    收藏  举报