字符串的包含——《编程之法》课后题答案

如果两个字符串中的字符一样,出现的次数也一样,只是出现的顺序不一样,则可以认为这两个字符串是兄弟字符串。例如,“bad”和“abd”即为兄弟字符串。
在书中提到的一个检验是否包含的算法是位运算算法,可将长字符串用位运算的方法计算出一个“签名”(58位二进制表示,‘A’ASCII值为65,’Z’ASCII值为122,两个字符差值属于[0,58]),在逐一将端字符串中的字符放入查找。方法十分巧妙。
但是对于本问题涉及到每个元素出现的个数问题,无法用上述算法实现,例如“bbc”包含于“abc”,但是二者并非是兄弟字符串。可以将原来的58位二进制“签名”改为用长度为58的数组表示,两个字符串出现对应的字符则在对应编号的位置++或–。

/* 字符串的包含 如果两个字符串的字符一样,出现次数也一样,则认为这两个字符串是兄弟字符串。 例如,“bad”和“abd”即为兄弟字符串。现提供一个字符串,在字典中快速找到他的一个兄弟字符串 */
#include <iostream>
using namespace std;

void FindBrother(char *s1, char *s2);
bool CharBrother(char* s1, char* s2, int nStart, int nEnd);

int main()
{

    char sInput[] = "abc" ;
    char sFind[] = "abcsdasdfasgagafgafcbagasfbcagSDfaaea";
    FindBrother(sInput,sFind);
    cin.get();
    return 0;
}

void FindBrother(char *s1,char *s2)
{
    /* 检测兄弟字符串个数 输入参数:*s1 ---待检测字符串 *s2 ---待检测字符串 输出参数: */
    int start = 0;
    int num=0;
    while (s2[start + strlen(s1) - 1] != '\0')
    {
        if (CharBrother(s1,s2,start,start+strlen(s1)-1))
        {
            num++;
        }
        start++;

    }
    cout << "The number of CharBrother is " << num << endl;

}

bool CharBrother(char* s1,char* s2,int nStart,int nEnd)
{
    /* 检测两个字符串是否是兄弟字符串 输入参数:*s1 ---待检测字符串 *s2 ---待检测字符串 nStart ---起始位置 nEnd ---截止位置 输出参数:false ---不是兄弟字符串 true ---是兄弟字符串 */
    int hash[58] = {0};              // (int) 'z'-'A' =57
    if (nStart>nEnd)
    {

        return false;
    }
    else
    {
        for (int i = 0; i < nEnd-nStart+1; i++)
        {
            ++hash[s1[i] - 'A'];
            --hash[s2[nStart+i] - 'A'];
        }
        for (int i = 0; i < 2*26; i++)
        {
            if (hash[i]!=0)
            {
                return false;
            }
        }

    }
    return true;
}

运行结果
字符串的包含——《编程之法》课后题答案_第1张图片

上述方法都借鉴了hash table的思路,能比较巧妙的解决问题。

你可能感兴趣的:(编程,算法,字符串)