一道题:给一个字符串,和一个字符集,求该字符串包含所有字符集的最短子串

比如字符集“abc”.个数为M。
字符串:“xxxbxxaxbxxbaxxaaxxcxx”
可知要求的最短子串是:baxxaaxxc。仔细分析最短串发现:
1。b与c在最短串中仅出现一次,正好是一头一尾。
2。中间的字符a,在最短串中可能出现了多次,但对于a而言如果只看它最后一次出现在最短串中,则之前不管是否出现过的都是无所谓的,比如最短串部分改成“bxxxxaxxc”,并不影响结果。

综合考虑上述两点,决定最短串长度的,只是字符集里的所有字符在最短串中最后一次出现的索引。为此,可设一个长为字符集个数M的数组,当遍历字符串时,不停的更新各字符
集最后出现的索引。同时,每字符集里的字符出现时,就要根据现有记录的索引去判断是否有最短子串产生。

时间复杂度:每次遍历遇到字符集出现,做一个判断O(M),因此总复杂度为O(N*M)。

 
  
 
  
#include 
#include 

#define N 100
#define M 3

char str[N] = "xbxaxaxbxaxcxcaxbxxaxbxcxxaxbcxaxcbcc";//母串
char ch[M] = "abc";//字符集

/*
函数功能:测试字符c是否在字符集中,若在,返回该字符在字符集中的索引
*/
int is_exit(char c)
{
	int i=0;
	for(i=0;i max_val  )
		{
			max_val = mindis_idx[i];
			max_idx = i;
		}
	}
	*pdis = max_val - min_val +1;
	*start_idx = min_val;
}

void show_substr(int start_idx,int d)
{
	char * ss = (char*)malloc(d+1);
	ss[d]=0;
	if(ss)
	{
		memcpy(ss,str+start_idx,d);
		printf("The substring=%s\n",ss);
	}
	free(ss);
}

void main()
{
	int mindis_idx[M];//记录当前字符集里每个字符在母串中的“当前”最大索引,这里的“当前”是指遍历索引的当前值
	memset(mindis_idx,-1,M*sizeof(int)); //初始化为-1,这非常关键,当计算最短距时,若遇到有-1,证明目前还没收集满所有字符集

	int d = N;//最短子串长
	int start_idx = 0;//当前最短子串的起始索引
	int i=0;
	for(;i



 
  
 
  
 
 

你可能感兴趣的:(算法与数据结构)