题目链接:点击打开链接
题目大意:给出n个串,找出最长公共子串,同长的输出字典序最小的。
似乎可以用kmp做,但那种东西对目前的我只可意会,不可手敲。。。于是就用map做了。
#include <cstdio>
#include <cstring>
#include <map>
#include <string>
using namespace std;
int main()
{
int t,i,j,n,k,l;
char s[66],s1[66];
map<string,int>a,b;
map<string,int>::iterator it;
scanf("%d",&t);
while(t--)
{
a.clear();
b.clear();
int x=0,flag=0;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%s",s);
a[s]=1;
}
it=a.begin(); //找出最小的序列
strcpy(s1,it->first.c_str());
int len=strlen(s1);
for(j=len-1;j>0;j--) //子串尾结点
{
for(i=0;i<j;i++) //子串头节点
{
l=0;
for(k=i;k<=j;k++)
{
s[l++]=s1[k];
}
s[l]='\0';
b[s]=l; //记录子串长度
x++; //记录子串数量
}
}
for(k=0;k<x;k++) //遍历所有子串
{
int c=0;
for(it=b.begin();it!=b.end();it++)
{
if(c<it->second)
{
c=it->second; //找出长度最大的子串,并且根据map储存特性,该子串也是同长度中字典序最小的
strcpy(s1,it->first.c_str());
}
}
b[s1]=-1; //长度标记为-1
flag=0;
for(it=a.begin();it!=a.end();it++)
{
if(it==a.begin()) //略过第一个串
continue;
strcpy(s,it->first.c_str());
if(!strstr(s,s1)) //若该子串不是公共子串则标记退出
{
flag=1;
break;
}
}
if(!flag) //若无标记则为公共子串,退出查找
{
printf("%s\n",s1);
break;
}
}
if(flag) //若无最长公共子串则输出
printf("no significant commonalities\n");
}
}