求字符串中最长无重复字符的子串
2015-09-01 10:28
453 查看
题目:求一个字符串中最长的没有重复字符的子串。
例如字符串“abcdaefgh”
使用hash表记录是否之前的字符出现,具体代码如下:
还有一种O(N)的算法,不是很好懂,先记录一下;
方法三:对字符串“axbdebpqawuva”构造下表:
表中,字符串有3个‘a’,有2个‘b’,其余为单一字符。next[]记录了下一个与之重复的字符的位置,如str[0]=str[8]=str[12]=‘a’,这时next[0]=8,next[8]=12,next[12]=13,其余同理。值得注意的是,对于没有重复字符的,next[]存储字符结束符‘\0’的下标,即13。
这里,first[i]表示i之后,第一次出现重复字符的那个位置。例如,str[0]之后,第一次出现的重复字符是str[5]=‘b’,当然,从str[1],str[2]开始也是一样。而从str[3]开始,要到str[12]才出现重复字符‘a’。可以证明,从str[i]起的最长符合要求的长度为first[i]-i,区间为[i,first[i]-1]由此得解。上述最长串是当i=3时,first[i]-i=12-3=9。结果最长无重复子串为“debpqawuv”。具体代码如下:
例如字符串“abcdaefgh”
使用hash表记录是否之前的字符出现,具体代码如下:
//O(N^2)的时间复杂度 int max_unique_substring2(char * str) { int i,j; int begin; int maxlen = 0; int hash[256]; int n = strlen(str); for(i=0; i<n; ++i) { memset(hash,0,sizeof(hash)); hash[str[i]] = 1; for(j=i+1; j<n; ++j) { if(hash[str[j]] == 0)//如果之前没有出现,那么就讲对应的位置进行置1,若出现了,则break hash[str[j]] = 1; else break; } if(j-i > maxlen)//break之后,比较当前的最大不重复子串的长度与之前的长度哪个长 { maxlen = j-i;//更新maxlen begin = i; } } printf("%.*s\n", maxlen, &str[begin]); return maxlen; }
还有一种O(N)的算法,不是很好懂,先记录一下;
方法三:对字符串“axbdebpqawuva”构造下表:
表中,字符串有3个‘a’,有2个‘b’,其余为单一字符。next[]记录了下一个与之重复的字符的位置,如str[0]=str[8]=str[12]=‘a’,这时next[0]=8,next[8]=12,next[12]=13,其余同理。值得注意的是,对于没有重复字符的,next[]存储字符结束符‘\0’的下标,即13。
这里,first[i]表示i之后,第一次出现重复字符的那个位置。例如,str[0]之后,第一次出现的重复字符是str[5]=‘b’,当然,从str[1],str[2]开始也是一样。而从str[3]开始,要到str[12]才出现重复字符‘a’。可以证明,从str[i]起的最长符合要求的长度为first[i]-i,区间为[i,first[i]-1]由此得解。上述最长串是当i=3时,first[i]-i=12-3=9。结果最长无重复子串为“debpqawuv”。具体代码如下:
//O(N)的时间复杂度 int max_unique_substring3(char * str) { int maxlen = 0; int begin = 0; int n = strlen(str); int * next = (int*)malloc(sizeof(int)*n); //next[i]记录了下一个与str[i]重复的字符的位置 int * first = (int*)malloc(sizeof(int)*(n+1)); //first[i]记录str[i]后面最近的一个重复点 int hash[256]; memset(hash,n,sizeof(hash)); first = n; for(int i=n-1; i>=0; i--) { next[i] = hash[str[i]]; hash[str[i]] = i; if (next[i] < first[i+1]) first[i] = next[i]; else first[i] = first[i+1]; //生成first[]表,复杂度是O(N)的 } for(int i=0; i<n; i++) { if (first[i]-i > maxlen) { maxlen = first[i]-i; begin = i; } } free(first); free(next); printf("%.*s\n", maxlen, &str[begin]); return maxlen; }
相关文章推荐
- Android NDK学习 <五> C++ 支持
- 软件开发模型
- 【备忘】java swing 焦点控制全纪录
- asp.net 文件下载
- c语言练习题 3-6 求差集
- Unity学习疑问记录之Awake和Update
- WPF mvvm模式下实现柱状图显示
- 项目实战:EMOS集成邮件系统搭建
- 8月第3周网络安全报告:.COM网站73.2%被篡改
- nyoj 417 死神来了
- Android NDK学习 <四> Application.mk简介
- SQL SERVER 与ACCESS、EXCEL的数据转换
- 问题:sqlserver if;结果: SqlServer if else和case
- 面试题 两个表字段相同更新表A
- JNI编程指南-第三章 基本类型、字符串、数组
- Case - Cass Assign
- container_of,typeof详解
- 监听器和拦截器原理
- iTunes Connect 上传APP报错: Communication error. please use diagnostic mode to check connectivity.
- java 匿名内部类 抽象类跟接口可以直接New出来啊~~