【发布时间】:2025-11-26 19:05:02
【问题描述】:
我需要从 C++ 中的一组文件名中计算最长的公共子字符串。
准确地说,我有一个 std::list 的 std::strings (或 QT 等价物,也可以)
char const *x[] = {"FirstFileWord.xls", "SecondFileBlue.xls", "ThirdFileWhite.xls", "ForthFileGreen.xls"};
std::list<std::string> files(x, x + sizeof(x) / sizeof(*x));
我需要计算所有字符串的 n 个不同的最长公共子字符串,在这种情况下,例如对于 n=2
"File" and ".xls"
如果我可以计算出最长的公共子序列,我可以将它剪掉并再次运行算法以获得第二长的,所以基本上可以归结为:
是否有(参考?)实现来计算 std::strings 的 std::list 的 LCS?
这不是一个好的答案,而是我拥有的一个肮脏的解决方案 - 对 QUrls 的 QList 进行暴力破解,只取最后一个“/”之后的部分。我很想用“正确”的代码替换它。
(我发现了http://www.icir.org/christian/libstree/ - 这会很有帮助,但我无法在我的机器上编译它。也许有人用过这个?)
QString SubstringMatching::getMatchPattern(QList<QUrl> urls)
{
QString a;
int foundPosition = -1;
int foundLength = -1;
for (int i=urls.first().toString().lastIndexOf("/")+1; i<urls.first().toString().length(); i++)
{
bool hit=true;
int xj;
for (int j=0; j<urls.first().toString().length()-i+1; j++ ) // try to match from position i up to the end of the string :: test character at pos. (i+j)
{
if (!hit) break;
QString firstString = urls.first().toString().right( urls.first().toString().length()-i ).left( j ); // this needs to match all k strings
//qDebug() << "SEARCH " << firstString;
for (int k=1; k<urls.length(); k++) // test all other strings, k = test string number
{
if (!hit) break;
//qDebug() << " IN " << urls.at(k).toString().right(urls.at(k).toString().length() - urls.at(k).toString().lastIndexOf("/")+1);
//qDebug() << " RES " << urls.at(k).toString().indexOf(firstString, urls.at(k).toString().lastIndexOf("/")+1);
if (urls.at(k).toString().indexOf(firstString, urls.at(k).toString().lastIndexOf("/")+1)<0) {
xj = j;
//qDebug() << "HIT LENGTH " << xj-1 << " : " << firstString;
hit = false;
}
}
}
if (hit) xj = urls.first().toString().length()-i+1; // hit up to the end of the string
if ((xj-2)>foundLength) // have longer match than existing, j=1 is match length
{
foundPosition = i; // at the current position
foundLength = xj-1;
//qDebug() << "Found at " << i << " length " << foundLength;
}
}
a = urls.first().toString().right( urls.first().toString().length()-foundPosition ).left( foundLength );
//qDebug() << a;
return a;
}
【问题讨论】:
-
这可能有用。 *.com/questions/2418504/…
-
我已经点击了数百个类似的问题但没有找到答案,包括上面的问题和*.com/questions/10248728/…。我得到的最接近的是homepage.virgin.net/cdm.henderson/site/cpp/lcs/index.htm,但那是用于子序列,而不是子字符串。
-
这是一个不平凡的问题。需要进行详尽的搜索。 (如果我的第一眼保持)
-
应该有一个使用后缀树的好解决方案,至少如果我理解 libstree 的库使用示例是正确的 - icir.org/christian/libstree/manual/c39.html。不幸的是,它不能编译并且对我的需要来说太复杂了。
-
您应该将所有匹配的子字符串保存在
vector中。对于每个字符串,每个字符都应该与其他字符进行比较。最小长度的字符串可以作为起点的参考,而int Find(const char* str, char ch)和void Sort(char* words[])等辅助函数将非常有用。
标签: c++ string sequence matching longest-substring