一开始感觉好难啊,除了暴力枚举我想不到其他办法。
然后就去看看别人的思路,发现竟然可以用暴力写!
我也没什么好顾虑的,然后就闷着头去写了。枚举样例第一个DNA串的所有长度大于3的子串,然后用这些和除了第一个DNA串KMP匹配即可。
遇到长的就替换一下,遇到长度相等的取字典序最小的继续替换…没什么弯。
我觉得难点吧,就是枚举所有子串那一部分,那个地方我写的很晕,在加上暴力的代码又那么长,越写越浑。最后把那一块单拉出来写的,最后清楚了。
先附上那一块的代码(枚举长度所有大于3的子串)
#include <iostream>
#include <cstring>
using namespace std;
char s[60];
char t[60];
int main()
{
cin >> s;
int len1 = strlen(s);
for(int i = 3; i<= len1; i++)
{
for(int j = 0; j < len1; ++j)
{
int len2 = 0;
for(int k = j;; k++)
{
t[len2++] = s[k];
if(len2 == i)
break;
}
t[len2] = '\0';
cout << t << endl;
}
}
return 0;
}
这个代码虽然把想要的子串全枚举了,但不符合要求的同样也列出来了(长度小于3的),
这样就会增加时间的复杂度(而且还不少)、、可以剪枝一下。
不过还好啦,我没剪枝最后输出的时候判断答案串长度大于等于3就行,也ac了。如果有强迫症的同学,可以在枚举子串的时候优化一下…
然后把kmp匹配嵌套进去就ok
下面是代码,代码有点长。不过暴力代码一般都这样,没办法,而且我写的可能有点臃肿,但我的思路我觉得还是清晰,就是读起来的时候乱七八糟的变量名可能让人费解…
不过咬牙看也能理解鸭!
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
char DNA[11][66], dna[66], ans[66];
int Next[66];
int len1, len2;
bool flag;
void getNext(char *dna)
{
int j = 0, t = -1;
Next[0] = -1;
while(j < len2)
{
if(t == -1 || dna[j] == dna[t])
{
t++;
j++;
Next[j] = t;
}
else
t = Next[t];
}
return;
}
bool KMP(char *DNA, char *dna)
{
int i = 0, j = 0;
while(i < len1 && j < len2)
{
if(j == -1 || DNA[i] == dna[j])
{
i++;
j++;
}
else
j = Next[j];
}
if(j >= len2)
return true;
else
return false;
}
int main()
{
int test;
cin >> test;
while(test--){
int n;
cin >> n;
for(int i = 0; i < n; ++i)
{
scanf("%s",DNA[i]);
}
int len_0 = strlen(DNA[0]);//len_0表示第一个串的长度
for(int i = 3; i <= len_0; ++i)//子串从3开始,最大的长度为len_0
{
for(int j = 0; DNA[0][j] != '\0'; ++j)
{
int len = 0;
for(int k = j;; k++)
{
dna[len++] = DNA[0][k];
if(len == i)
break;
}
dna[len] = '\0';//以上是列举子串
len2 = strlen(dna);//子串长度
getNext(dna);
for(int j = 1; j < n; ++j)
{
len1 = strlen(DNA[j]);//要匹配的主串长度
flag = KMP(DNA[j],dna);
if(!flag)
break;
else
continue;
}
if(flag)
{
int c = strlen(ans);//答案串的长度。
//所以一开始答案串的长度为0,我在下面初始化了
if(c < len2)
strcpy(ans,dna);//留长的
if(c == len2)
{
if(strcmp(dna,ans)<0)
strcpy(ans,dna);//留小的
}
}
}
}
if(strlen(ans)>=3)//输出长度大于等于3的答案串
cout << ans << endl;
else
cout << "no significant commonalities" << endl;
memset(ans,0,sizeof(ans));//放在这儿初始化了,因为发现错了才临时加的,放前面比较好
}
return 0;
}