HDU 1238 Substrings(KMP+暴力枚举)

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. 
Input
The 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. 
Output
There 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 的肯定也找不到,所以这时候就直接更新答案然后退出就好了。

 因为每个串有正有逆,所以我们直接把正串和逆串都存起来,只要在其中一个找到目标串就可以了。

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



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值