You are given a number of case-sensitive strings of alphabetic characters, find the largest string X, such that either X, or its inverse can be found as a substring of any of the given strings.
2 3 ABCD BCDFF BRCD 2 rose orchid
2 2
【题解】
题意很简单,就是求m个串的最长公共子串,每个串可以正着也可以逆着,由于题目给的数据范围比较小,所以直接暴力求解;
把第一个串的每一个子串当作目标串,每次遍历剩下的串,查找该子串(因为公共子串也一定在第一个串中),这里有技巧,那就是目标串从短到长递增遍历,这样如果某次长度为 i 的子串不能满足,那么长度>i 的肯定也找不到,所以这时候就直接更新答案然后退出就好了。
因为每个串有正有逆,所以我们直接把正串和逆串都存起来,只要在其中一个找到目标串就可以了。
这里有个STL函数 strstr(s1,s2)表示在串1中查找串2,如果找到就返回其首元素下标值,否则返回null;
有这个函数可以是代码更简洁,当然自己手写也是可以的。
这个题和我前几天做的一题做法类似,都是暴力枚举,推荐试试:POJ 3080
解题博客:http://blog.csdn.net/qq_38538733/article/details/77278363
【AC代码】
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=105;
int m,n;
char str[N],s3[N];
struct sstr
{
char s1[N],s2[N]; //保存原串和原串的逆串
}ss[N];
int check()
{
int ans=0;
int len3=strlen(s3);
for(int i=1;i<=len3;++i)//遍历长度为i的子串
{
bool tag=0;//标记剩下的m-1个串中是否找到长为i的串
for(int j=0;j<=len3-i;++j)//遍历长度为i的不同子串
{
int k=0;
int sk=j;
while(sk<i+j){
str[k++]=s3[sk++];//目标串
}
str[k]='\0';//注意 最好加上 否则有时候出bug却找不着 养成好习惯
int p=0;//标记剩下的m-1个串中是否有目标串
for(int l=1;l<m;++l)//遍历剩下的串
{
if((!strstr(ss[l].s1,str))&&(!strstr(ss[l].s2,str)))//查找子串
{
p=1;//没找着就标记为1
break;
}
}
if(p==0)//如果都找着了 就直接更新答案 退出
{
tag=1;
ans=i;
break;
}
}
if(!tag) break;//注意!!很重要的剪枝--如果长度为i的都没找着 那长度>i的一定也找不着
}
return ans;
}
int main()
{
int t;
char str1[N];
scanf("%d",&t);
while(t--)
{
scanf("%d",&m);
for(int i=0;i<m;++i)
{
scanf("%s",str1);
if(!i)
strcpy(s3,str1);//以第一个串为根串
else{
strcpy(ss[i].s1,str1);//保存原串
reverse(str1,str1+strlen(str1)); //逆
strcpy(ss[i].s2,str1); //保存逆串
}
}
int ans=check();
reverse(s3,s3+strlen(s3));//根串求逆后再查找
ans=max(ans,check()); //保存最大值即答案
printf("%d\n",ans);
}
return 0;
}