您的位置:首页 > 其它

HDU 1238 Substrings(KMP+暴力枚举)

2017-08-21 17:04 387 查看
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. 

InputThe first line of the input file contains a single integer t (1 <= t <= 10), the number of test cases, followed by the input data for each test case. The first line of each test case contains a single integer n (1 <= n <= 100), the number of given
strings, followed by n lines, each representing one string of minimum length 1 and maximum length 100. There is no extra white space before and after a string. 

OutputThere should be one line per test case containing the length of the largest string found. 

Sample Input
2
3
ABCD
BCDFF
BRCD
2
rose
orchid


Sample Output
2
2


 【题解】

  题意很简单,就是求m个串的最长公共子串,每个串可以正着也可以逆着,由于题目给的数据范围比较小,所以直接暴力求解;

 把第一个串的每一个子串当作目标串,每次遍历剩下的串,查找该子串(因为公共子串也一定在第一个串中),这里有技巧,那就是目标串从短到长递增遍历,这样如果某次长度为 i 的子串不能满足,那么长度>i 的肯定也找不到,所以这时候就直接更新答案然后退出就好了。<
4000
/p>
 因为每个串有正有逆,所以我们直接把正串和逆串都存起来,只要在其中一个找到目标串就可以了。

这里有个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
,s3
;

struct sstr
{
char s1
,s2
; //保存原串和原串的逆串
}ss
;

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
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: