您的位置:首页 > 其它

看书做题动手!【再简单也要实践】

2008-03-24 22:12 225 查看
今天看书看到一个题目说的是,有一个字符串“ABCD”,设计一个算法获得其所有的子串。首先我需要澄清什么是串这个概念。
所谓串指的是:由0个或者多个字符组成的有穷序列。
子串:一个串中任意个连续字符组成的子序列,叫做这个串的子串。
根据这个定义那么一个串中最大的子串就是其本身了,最小的子串就是为空。
根据定义手算的话不难得出:
"ABCD"的非空子串是:A、B、C、D、AB、BC、CD、ABC、BCD、ABCD
分析的方法很简单,就是“划线法”:
首先是长度为一的子串:A、B、C、D。
长度为二的子串:AB、BC、CD
长度为三的子串:ABC、BCD
长度为四的子串:ABCD
简单分析一下可以大胆猜想求一个串的非空子串的个数的方法,如下公式:
R = 1+2+3+...+N
N:子串字符个数。
R:非空子串个数。
利用数学归纳法很容易证明。
好了,现在开始设计算法,首先把ABCD有序字符列编号为0123
那么就是要输出0、1、2、3、01、12、23、012、123、0123
接下来,开始找规律,输出的各类长度的子串刚好是四个等于串的字符个数,而输出的子串随着子串中字符的增加而有规律递减,呵呵,可以设计类似如下循环:
for i = 0 to N-1
for j = i to 0
这样0-->0---N-1
1->0---N-2 、1---N-1
… …
i->0---N-1-i、1---N-i、......、i---N-1
试着写写
const int nCount = strCS.GetLength();
for ( int nIdxI = 0 ; nIdxI < nCount; ++nIdxI )
{
for ( int nIdxJ = nIdxI; nIdxJ >= 0; --nIdxJ )
{
rgpBContainer.push_back(strCS.Mid( nIdxJ, nCount - nIdxI ));
}
}

设计完了这个求非空子串的算法,我想可以展开一下,若要设计这样的算法呢:输入"ABCD",得到:A、B、C、D、AB、AC、AD、BC、BD、CD、ABC、ABD、ACD、BCD、ABCD 。

还是很有规律的,其中有序性是一直保持的!
试着用分治法分析一下:
ABCD ---- ABCD : ABCD、 A、 BCD、AB、ACD、ABC、ABD、AC、AD、 B、 CD、BC、BD、C、D
A<--BCD ---- A / BCD : A、 BCD、AB、ACD、ABC、ABD、AC、AD、 B、 CD、BC、BD、C、D
B<--CD ---- B / CD : B、 CD、BC、BD、C、D
C<--D ---- C / D : C、D
看出规律了吧,将字符串的每个第一个字符分离出来,然后将剩余的字符继续做分离,最后分离到最后两个字符,然后将其回溯,与上次分离的第一个字符组合,最后便可以得到所有的情况了,换句话说就是之前求子串的情况加上一个首字母,也就是先将首字母分离,在求剩余字符串的子串,然后与首字母组合。

到了这个地方还是自己需要跟自己强调一下,算法大致轮廓描述出来的时候,往往是最“掉以轻心”的时候,认为自己知道怎么去做了,于是乎就不去动手写程序来验证了,须不知,算法描述与完全实现之间是有一个“鸿沟”的,这个沟的深度与宽度就是随着自己想当然地似是而非地认为正确的时候越来越大越来越深,直到有一天自己跌落进去后悔莫及,打个比方快速排序这个算法应该是大家都很熟悉的,我在公司做过实验让同事写这个算法,结果就是漏洞百出,有的甚至惨不忍睹!!!,因此,知行合一这四个字的分量大家自行掂量着看了,好了不扯远了,这里我们根据这个描述试着写写它的实现:
void GetAllBunches( CString &strCS, std::vector<CString>& rgpBunches)
{
const int nCount = strCS.GetLength();
if ( nCount < 1)
return;
CString strFirstLetter = strCS[0];
strCS = strCS.Mid(1, nCount-1);
for (int nIdI = 0; nIdI < nCount-1; ++nIdI)
{
for (int nIdJ = nIdI; nIdJ >= 0; --nIdJ)
{
rgpBunches.push_back( strFirstLetter + strCS.Mid(nIdJ,nCount-1-nIdI) );
}
}

rgpBunches.push_back( strFirstLetter );
GetAllBunches( strCS, rgpBunches );
}

OK,到这里基本上就完结了,但是如果说你需要一个实用的版本,就应该用标准c++来写,而不是依赖于MFC相关的类实现!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: