我有一些字符串,字符不会在一个字符串中重复。 例如:" AABC"是不可能的。
我想通过它们的公共子字符串将它们聚集到集合中。 例如:" ABC,CDF,GHP"将集群分为两组 {ABC,CDF},{GHP}。
具有一个或多个公共子字符串的几个字符串将在一个集合中。 没有公共子字符串和任何其他字符串的字符串将是一个集合本身。 所以保持最小的数量。
例如: 1." ABC,AHD,AKJ,LAN,WER"将是两套{ABC,AHD,AKJ,LAN},{WER}。 2." ABC,BDF,HLK,YHT,PX"将是3集{ABC,BDF}。{HLK,YHT},{PX}。
我认为找到一个与他人没有共同点的字符串很容易;
for(i=0; i< strings.num; i++)
{ str1 = strings[i];
bool m_com=false;
for(j=0;j < strings.num; j++ )
{
str2=strings[j];
if(hascommon(str1,str2))
m_com=true;
}
if(!m_com)
{
str1 has no common substring with any string,
}
}
现在我正在考虑其他人,如何对它们进行分类,是否有适合此的算法?
输入: 字符串(字符不重复)
输出: 集(保持集数尽可能小)
我知道这涉及找到常见的子串问题和聚类。 但我不熟悉聚类技术,所以我希望有一些 可以推荐我这样的算法。
虽然我正在寻找做到这一点的好方法,但我也很欣赏其他人的建议。
提示:实际上,这些字符串是图表中两点之间的简单路径。我想找到去除所有这些路径的边缘。这些边缘的数量应该是最小的。因此,对于AB,BC,CD,它意味着存在单个路径ABCD。 我写下了一个算法来查找我的常见子串(我的情况更简单)。我想我可能会在聚类过程中使用这个算法来测量相似性。
我可能有两条路径,{ABC,ADC},删除A或删除B都可以分割路径。 或者我可以{ABC,ADC,HG},所以删除{A,H}或{CH},或{CG},或{AG}都可以。
我以为我可以通过查找常见的子字符串来解决这个问题,然后决定删除边缘的位置。
答案 0 :(得分:1)
首先应该指出一件事:
For any two strings, "having common substring" is really equivalent to "having common letter". Thus we can replace the condition by "having common letter".
考虑其顶点为字符串的图G
,当且仅当它们具有公共字母时,两个字符串由边连接。那么你真的要求将图G
分成连接的组件。这可以使用标准图形操作算法,c.f。轻松完成。 the wiki page here
建立图表的任务仍然是什么。这也很简单:首先,创建26个框,标记为A
到Z
,并读取每个字符串一次。如果字符串包含字母A
,则将其(或其索引)放入框A
等。最后,一个框内的字符串边缘相互连接。
可以进一步优化,但我想这取决于输入数据的性质。
答案 1 :(得分:0)
您必须使用Heap算法为您的工作创建排列https://en.wikipedia.org/wiki/Heap&#39; s_algorithm
答案 2 :(得分:0)
与WhatsUp相反,我假设你希望子集中的任何两个字符串都有一个共同的子字符串。这意味着对于{AB, BC, CD}
,AB
不是有效的解决方案,因为CD
和{{1}}没有共同的子字符串。
正如Whatsup已经指出的那样,你可以将你的字符串表示为一个图形,其中顶点是字符串,如果它们有一个共同的字符,则边缘从一个到另一个。
如果我们不接受链(如开头所述),问题就变成了minimum clique cover,遗憾的是NP完全。