Skip to content

Instantly share code, notes, and snippets.

@sunxu
Created November 15, 2012 06:04
Show Gist options
  • Save sunxu/4076900 to your computer and use it in GitHub Desktop.
Save sunxu/4076900 to your computer and use it in GitHub Desktop.
@陈利人 从一个长字符串中查找包含给定字符集合的最短子串。例如,长串为“aaaaaaaaaacbebbbbbdddddddcccccc”,字符集为{abcd},那么最短子串是“acbebbbbbd”。如果将条件改为“包含且只包含给定字符集合”,你的算法和实现又将如何改动。
//
// minsubstr.c
// Test
//
// Created by 孙 旭 on 12-11-15.
// Copyright (c) 2012年 孙 旭. All rights reserved.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define true 1
#define false 0
#define error -1
static void add_char_to_hash(int* hash, int hash_size, char chr){
for(int i = 0; i < hash_size; i++){
if(chr == hash[2*i]){
hash[2*i+1]++;
return;
}
}
}
static void remove_char_from_hash(int* hash, int hash_size, char chr){
for(int i = 0; i < hash_size; i++){
if(chr == hash[2*i]){
hash[2*i+1]--;
return;
}
}
}
static int check_hash_full(int* hash, int hash_size){
for(int i = 0; i < hash_size; i++){
if(hash[2*i+1] < 1)
return false;
}
return true;
}
int min_sub_str(const char* str, const char* set, int* start, int* end){
*start = -1;
*end = -1;
if(NULL == str || NULL == set)
return false;
int str_len = strlen(str);
int set_size = strlen(set);
*end = str_len;
int* hash= (int*)malloc(sizeof(int) * 2 * set_size);
if(NULL == hash)
return error;
for (int i = 0; i < set_size; i++) {
hash[2*i] = set[i];
hash[2*i+1] = 0;
}
int t_start = 0; //tmp start
int t_end = -1; //tmp end
while (str[t_start] == str[t_start+1]) {
t_start++;
}
add_char_to_hash(hash, set_size, str[t_start]);
int index = t_start+1;
while (t_start < str_len || index < str_len) {
add_char_to_hash(hash, set_size, str[index]);
int is_full = check_hash_full(hash, set_size);
if (is_full) {
t_end = index;
do{
remove_char_from_hash(hash, set_size, str[t_start]);
t_start++;
}while (check_hash_full(hash, set_size));
if(t_end - t_start + 1 < *end - *start){
*start = t_start - 1;
*end = t_end;
}
}
index++;
}
if (-1 == *start) {
return false;
}
return true;
}
int main(){
char str[] = "aaaaaaaaaaacbebbbbbdddddddcccccc";
char set[] = "abcd";
int start, end;
if(min_sub_str(str, set, &start, &end)){
printf("from %d to %d \n", start, end);
for (int i = start; i <= end; i++) {
printf("%c", str[i]);
}
}else{
printf("not found \n");
}
return 0;
}
@sunxu
Copy link
Author

sunxu commented Nov 15, 2012

如果将条件改为“包含且只包含给定字符集合”,你的算法和实现又将如何改动。

此时,在73行的while中检测hash是否有值大于等于2。
如果有,则
remove_char_from_hash(. . str[t_start]);t_start++;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment