二分 - Substrings - HDU - 1238 + Corporate Identity - HDU - 2328

二分 - Substrings - HDU - 1238 + Corporate Identity - HDU - 2328

一、Substrings - HDU - 1238

题意:

T 组 测 试 用 例 , 每 组 包 括 n 个 给 定 的 字 符 串 , 要 求 在 这 n 个 字 符 串 中 的 某 个 字 符 串 的 子 串 , 或 者 这 个 子 串 的 翻 转 也 是 其 他 字 符 串 的 子 串 。 求 满 足 条 件 的 子 串 的 最 大 长 度 。 T组测试用例,每组包括n个给定的字符串,要求在这n个字符串中的某个字符串的子串,\\或者这个子串的翻转也是其他字符串的子串。求满足条件的子串的最大长度。 Tnn

Sample Input:
2
3
ABCD
BCDFF
BRCD
2
rose
orchid

Sample Output:
2
2

数据范围:
1 < = T < = 10 , 1 < = n < = 100 , T i m e   l i m i t : 1000 m s , M e m o r y   l i m i t : 32768 k B 1 <= T<= 10,1 <= n <= 100,\\Time \ limit:1000 ms,Memory \ limit:32768 kB 1<=T<=101<=n<=100Time limit1000msMemory limit32768kB

题解:

由 于 数 据 范 围 比 较 小 , 直 接 暴 力 枚 举 也 是 可 以 过 的 。 从 小 到 大 枚 举 第 一 个 字 符 串 的 所 有 子 串 , 再 分 别 将 每 个 子 串 与 剩 下 的 n − 1 个 字 符 串 进 行 匹 配 , 有 n 个 子 串 , n − 1 个 字 符 串 , 匹 配 一 次 的 是 O ( n ) 的 , 时 间 复 杂 度 是 O ( T n 3 ) 的 。 由于数据范围比较小,直接暴力枚举也是可以过的。\\从小到大枚举第一个字符串的所有子串,再分别将每个子串与剩下的n-1个字符串进行匹配,\\有n个子串,n-1个字符串,匹配一次的是O(n)的,时间复杂度是O(Tn^3)的。 n1nn1O(n)O(Tn3)

这 里 可 以 二 分 枚 举 子 串 的 最 大 长 度 , 然 后 再 判 断 , 时 间 复 杂 度 O ( T n 2 l o g n ) 。 这里可以二分枚举子串的最大长度,然后再判断,时间复杂度O(Tn^2logn)。 O(Tn2logn)


代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N=110;
int t,n;
string s[N];

bool check(int x)
{
    string tmp;
    for(int i=0;i+x-1<s[1].size();i++)
    {
        tmp=s[1].substr(i,x);
        for(int j=2;j<=n;j++)
        {
            if(s[j].find(tmp,0)==-1)
                break;
            else if(j==n) return true;
        }

        reverse(tmp.begin(),tmp.end());
        for(int j=2;j<=n;j++)
            if(s[j].find(tmp,0)==-1)
                break;
            else if(j==n) return true;
    }

    return false;
}

int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(int i=1;i<=n;i++) cin>>s[i];

        int l=0,r=100;
        while(l<r)
        {
            int mid=l+r+1>>1;
            if(check(mid)) l=mid;
            else r=mid-1;
        }

        printf("%d\n",l);
    }
    return 0;
}


二、Corporate Identity - HDU - 2328

题意:

多 组 测 试 用 例 , 每 组 包 括 n 个 字 符 串 , 要 找 这 n 个 字 符 串 中 最 长 的 相 同 子 串 , 若 有 多 个 满 足 条 件 的 子 串 , 输 出 字 典 序 最 小 的 。 多组测试用例,每组包括n个字符串,要找这n个字符串中最长的相同子串,\\若有多个满足条件的子串,输出字典序最小的。 nn

Sample Input:
3
aabbaabb
abbababb
bbbbbabb
2
xyz
abc
0

Sample Output:
abb
IDENTITY LOST

数据范围:

2 ≤ n ≤ 4000 , 字 符 串 长 度 m < = 200 T i m e   l i m i t : 3000 m s , M e m o r y   l i m i t : 32768 k B 2 ≤ n ≤ 4000,字符串长度m<=200\\Time \ limit:3000 ms,Memory\ limit:32768 kB 2n4000m<=200Time limit3000msMemory limit32768kB

题解:

与 上 一 题 类 似 , 区 别 在 于 先 要 保 证 长 度 最 大 , 再 保 证 字 典 序 最 小 。 可 以 用 a n s 来 记 录 当 前 最 长 且 字 典 序 最 小 的 子 串 , 初 始 化 为 ′ { ′ , ( 字 典 序 大 于 z ) 。 时 间 复 杂 度 O ( n m l o g m ) 。 与上一题类似,区别在于先要保证长度最大,再保证字典序最小。\\可以用ans来记录当前最长且字典序最小的子串,初始化为'\{',(字典序大于z)。 \\时间复杂度O(nmlogm)。 ans{(z)O(nmlogm)


代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N=210;

int n;
string s[4010],ans="{";

bool check(int x)
{
    string tmp;
    bool flag=false;
    for(int i=0;i+x-1<s[1].size();i++)
    {
        tmp=s[1].substr(i,x);
        for(int j=2;j<=n;j++)
            if(s[j].find(tmp,0)==-1)
                break;
            else if(j==n)
            {
                if(ans.size()<tmp.size()) ans=tmp;   //先保证长度
                else if(ans.size()==tmp.size()&&ans>tmp) ans=tmp;  //再保证字典序
                flag=true;
            }
    }
    return flag;
}

int main()
{
    while(~scanf("%d",&n),n)
    {
        ans="{";
        for(int i=1;i<=n;i++) cin>>s[i];

        int l=0,r=200;
        while(l<r)
        {
            int mid=l+r+1>>1;
            if(check(mid)) l=mid;
            else r=mid-1;
        }
        if(ans!="{") cout<<ans<<endl;
        else puts("IDENTITY LOST");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值