C++查找两个字符串[汉字]所有的最大公共字符串

    最近做项目,遇到匹配一句话来源于哪一条规则(公司定的规则),比如:

规则1:%@今天心情由低落变高兴;

规则2:%@今天心情由高兴变开心;

规则3:%@今天心情由低落变开心;

规则4:%@今天的心情呀由开心变高兴。(自己瞎写的规则,只是为了举例说明,勿喷)

现在要做的处理是,输入一条字符串,匹配查找该字符串来源于那一条规则,

输入字符串:小明今天心情由高兴变开心。

起初是想找原句与各规则句的最长公共字符串,可能会出现输入语句与各规则语句公共字符串长度相等的情况,仍不容易区分来自哪一条规则。

最终想到何不找出输入句与各规则句所有的最长公共字符串(可能有歧义),最长是指连续的,比如说,由、高兴、由高兴、变、开心等都是输入语句与规则句的公共字符串而此时的最长公共字符串是 “由高兴变开心”.

而所有的最长公共字符串则包括“今天”、“心情”、“由开心变高兴”(有点啰嗦)。

对于字符串的匹配考虑到输入语句和规则语句都含有中文,所以要将各语句在匹配是转化为宽字节,即string->wstring.

//string 转wstring

std::wstring s2ws(const std::string s)
{
    setlocale(LC_ALL,"zh_CN.UTF-8");//linux下默认编码UTF-8 windows下还没测试因该是GBK吧

    const char* _Source = s.c_str();
    size_t _Dsize = s.size() + 1;
    wchar_t *_Dest = new wchar_t[_Dsize];
    wmemset(_Dest, 0, _Dsize);
    mbstowcs(_Dest,_Source,_Dsize);
    wstring result = _Dest;
    delete []_Dest;

    setlocale(LC_ALL, "C");

    return result;
}
/*

顺便将wstring转string也写出来
*/
std::string ws2s(const std::wstring ws)
{
    string curLocale = setlocale(LC_ALL, NULL);        // curLocale = "C";

    setlocale(LC_ALL, "chs");

    const wchar_t* _Source = ws.c_str();
    size_t _Dsize = 2 * ws.size() + 1;
    char *_Dest = new char[_Dsize];
    memset(_Dest,0,_Dsize);
    wcstombs(_Dest,_Source,_Dsize);
    string result = _Dest;
    delete []_Dest;

    setlocale(LC_ALL, curLocale.c_str());

    return result;

}
网上看到一篇python代码求所有最长共有字符串拿来借鉴转为C++,原文地址:

https://blog.csdn.net/weixin_43296805/article/details/83340720

C++代码:

void getNumofCommonSubstr(std::wstring str1, std::wstring str2, std::map<int, std::wstring>& map_maxStr)
{
    int lstr1 = str1.size();
    int lstr2 = str2.size();
    int record[lstr1+1][lstr2+1];
    int maxNum = 0;
    int max_start = 0;
    for(int i=0; i<lstr1; i++)
    {
        for(int j=0; j<lstr2; j++)
        {
            record[i][j]=0;
        }
    }
    for(int i=0; i<lstr1; i++)
    {
        for(int j=0; j<lstr2; j++)
        {
            if(str1[i]==str2[j])
            {
                wchar_t s1 = str1[i];
                wchar_t s2 = str1[j];
                record[i+1][j+1]=record[i][j]+1;
                if(record[i+1][j+1]>maxNum)
                {
                    maxNum = record[i+1][j+1];
                    int p = i+1;
                    max_start = i+1 -maxNum;
                    map_maxStr[max_start]=str1.substr(p-maxNum,maxNum);
                }
            }
        }
        maxNum = 0;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值