每天學習一算法系列(30)(給一個很長的字符串str 還有一個字符集比如{a,b,c} 找出str 裏包含{a,b,c}的最短子串。要求O(n).)

題目:

給一個很長的字符串str 還有一個字符集比如{a,b,c} 找出str 裏包含{a,b,c}的最短子串。要求O(n).

比如,字符集是a,b,c,字符串是abdcaabcx,則最短子串爲abc。

 

思路一:

用兩個變量Front, Rear 指向這個字串(str)區間的頭和尾,開始的時候同指向字符串首地址,用一個變量int achSubCnt[256]={0}記錄字符集a,b,c 個數,用另外一個變量int achCnt[256] = {0}記錄當前這個子串裏a,b,c各自出現的個數,一個變量i32CurSum記錄當前Front,Rear指向的區間中有多少個字符集裏面的元素了,Rear 一直加,然後判斷Rear所指的字符是否是在字符集中,如果是那麼更新achCnt[]和i32CurSum的值,直到i32CurSum等於字符集個數,然後Front++,直到achCnt[]裏某個字符個數爲0,這樣就找到一個符合條件的字串了。
繼續前面的操作,就可以找到最短的了。(如果題目要求把所有匹配字符集中的字符串羅列出來也是可以的,這樣還可以不進行匹配字串長度的比較)

 

代碼如下:

/*--------------------------------
Copyright by yuucyf.	2011.08.24
---------------------------------*/

#include "stdafx.h"
#include <iostream>
using namespace std;

#define		CHAR_COUNT		256
typedef struct tagPosition
{
	int i32Front;
	int i32Rear;

	tagPosition()
	{
		i32Front = i32Rear = 0;
	}
}S_StrPos;


bool FindShortSubString(const char* pszStr, const char *pszSubStr, S_StrPos &sShortSubStr)
{
	if (NULL == pszStr || NULL == pszSubStr)
		return false;
	int i32Len = _tcslen(pszStr);
	int i32SubLen = _tcslen(pszSubStr);
	if (i32Len <= 0 || i32SubLen <= 0)
		return false;
	
	sShortSubStr.i32Front = sShortSubStr.i32Rear = 0;
	
	int i32CurSum = 0;
	int achSubCnt[CHAR_COUNT] = {0};
	int achCnt[CHAR_COUNT] = {0};
	int i32I = 0;
	for (i32I = 0; i32I < i32SubLen; i32I++)
	{
		achSubCnt[pszSubStr[i32I]]++;
	}

	int Front = 0, Rear = 0;
	while (Front < i32Len && Rear < i32Len)
	{
		if (i32CurSum != i32SubLen)
		{
			if (achSubCnt[pszStr[Rear]] > 0)
			{
				achCnt[pszStr[Rear]]++;
				if (achSubCnt[pszStr[Rear]] >= achCnt[pszStr[Rear]])
					i32CurSum++;
			}

			Rear++;
		}
		else
		{
			achCnt[pszStr[Front]]--;
			if (achCnt[pszStr[Front]] == 0)		//Find a sub string.
			{
				if (sShortSubStr.i32Rear == 0)
				{
					sShortSubStr.i32Front = Front;
					sShortSubStr.i32Rear = Rear;
				}
				else if ((sShortSubStr.i32Rear - sShortSubStr.i32Front) > (Rear - Front))
				{
					sShortSubStr.i32Front = Front;
					sShortSubStr.i32Rear = Rear;
				}

				i32CurSum--;
			}
			Front++;
		}
	}

	//可能是Rear已經到達字符串尾,可是還存在i32CurSum == i32SubLen的情況,
	//所以要從Front開始往前遍歷,找到最後一個滿足條件的字串。
	while (i32CurSum == i32SubLen)
	{
		achCnt[pszStr[Front]]--;
		if (achCnt[pszStr[Front]] == 0)		//Find a sub string.
		{
			if (sShortSubStr.i32Rear == 0)
			{
				sShortSubStr.i32Front = Front;
				sShortSubStr.i32Rear = Rear;
			}
			else if ((sShortSubStr.i32Rear - sShortSubStr.i32Front) > (Rear - Front))
			{
				sShortSubStr.i32Front = Front;
				sShortSubStr.i32Rear = Rear;
			}

			i32CurSum--;
		}
		Front++;
	}

	return (sShortSubStr.i32Rear != 0);
}


int _tmain(int argc, _TCHAR* argv[])
{
	char aszStr[] = "abdcaabcx";
	char aszSubStr[] = "abc";
	S_StrPos sStrPos;

	if (FindShortSubString(aszStr, aszSubStr, sStrPos))
	{
		cout << "最短的字串爲:";
		for (int i32I = sStrPos.i32Front; i32I < sStrPos.i32Rear; i32I++)
			cout << aszStr[i32I];
		cout << endl;
	}
	return 0;
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章