您的位置:首页 > 其它

40.给字符串s1、s2,在s1中找包含s2里所有字符的最小子串

2011-08-04 12:40 281 查看
题目:一串首尾相边的珠子(m个),有N种颜色,设计 一种算法,取出其中一段,要求包含所有N种颜色,并使长度最短。

给一个字符串s1,和一个小串s2,求算法能在s1中找到包含s2里所有字符的最小子串。比如:

s1 = “ADOBECODEBANC”

s2 = “ABC”
最小子串是 “BANC”,要求O(N)的算法。

此两题是一样的。

思路:

设置两个指针p1,p2,初始化指向s1串的开头。当p1, p2指针之间的s1子串字母包含s2全部字符时,p1++,当两个指针之间的子不完全包含s2中的全部字符时p2++(增加指针间距),与此同时记录合法包含子串的的最小串的起始位置。

在进行上述伸缩时,如何快速的记录s2串的包含情况?使用一个hash 表,记录字符的出现次数,当p1++时,将对应字母的计数减1,当p2++时,将对应字母的计数加1。

#include<iostream>

using namespace std;

int FindMinSubString(char* s1, char* s2)
{

int hash_table[256];

/*
初始化 hash 表,s2中出现的字符标记为0,
其他标记为负数
*/
for (int i=0; i<256; i++)
{
hash_table[i] = -1;
}

for (char* p = s2; *p != '\0'; p++)
{
hash_table[*p] = 0;
}

char* p1 = s1;
char* p2 = s1;

//最短长度
int min_len = 2100000000;

//最小串的起止位置
char* min_p1 = s1;
char* min_p2 = s1;

//记录p1 p2之间的合法字符种类数 ,count == s2_len 包含s2
int count = 0;

int s2_len = strlen(s2);

/*
注意p2到达s1的结束位置后,不能结束
应当继续收缩,直到不含s2
*/
while(*p2 !='\0' || s2_len==count)
{

//p1...p2不包含s2
if (count<s2_len)
{
//属于s2中出现的字符
if (hash_table[*p2] == 0)
{
count++;
hash_table[*p2]++;
}
else if (hash_table[*p2] > 0)
{
hash_table[*p2]++;
}

p2++;
}

//不能用else 因为在上一个if语句中对count++;
if(count == s2_len)
{
if (p2-p1 < min_len)
{
min_p1 = p1;
min_p2 = p2;
min_len = p2-p1;
}

//收缩
hash_table[*p1]--;
if (hash_table[*p1] == 0)
{
count--;
}
p1++;
}
}

//输出
while(min_p1 < min_p2)
{
cout<<*min_p1;
min_p1++;
}
cout<<endl;

return min_len;
}
int main()
{
char str1[]="abdddcaabc";
char str2[]="abc";
cout<<FindMinSubString(str1,str2);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐