最近做项目,遇到匹配一句话来源于哪一条规则(公司定的规则),比如:
规则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;
}
}