二分 - Substrings - HDU - 1238 + Corporate Identity - HDU - 2328
文章目录
一、Substrings - HDU - 1238
题意:
T 组 测 试 用 例 , 每 组 包 括 n 个 给 定 的 字 符 串 , 要 求 在 这 n 个 字 符 串 中 的 某 个 字 符 串 的 子 串 , 或 者 这 个 子 串 的 翻 转 也 是 其 他 字 符 串 的 子 串 。 求 满 足 条 件 的 子 串 的 最 大 长 度 。 T组测试用例,每组包括n个给定的字符串,要求在这n个字符串中的某个字符串的子串,\\或者这个子串的翻转也是其他字符串的子串。求满足条件的子串的最大长度。 T组测试用例,每组包括n个给定的字符串,要求在这n个字符串中的某个字符串的子串,或者这个子串的翻转也是其他字符串的子串。求满足条件的子串的最大长度。
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<=10,1<=n<=100,Time limit:1000ms,Memory limit:32768kB
题解:
由 于 数 据 范 围 比 较 小 , 直 接 暴 力 枚 举 也 是 可 以 过 的 。 从 小 到 大 枚 举 第 一 个 字 符 串 的 所 有 子 串 , 再 分 别 将 每 个 子 串 与 剩 下 的 n − 1 个 字 符 串 进 行 匹 配 , 有 n 个 子 串 , n − 1 个 字 符 串 , 匹 配 一 次 的 是 O ( n ) 的 , 时 间 复 杂 度 是 O ( T n 3 ) 的 。 由于数据范围比较小,直接暴力枚举也是可以过的。\\从小到大枚举第一个字符串的所有子串,再分别将每个子串与剩下的n-1个字符串进行匹配,\\有n个子串,n-1个字符串,匹配一次的是O(n)的,时间复杂度是O(Tn^3)的。 由于数据范围比较小,直接暴力枚举也是可以过的。从小到大枚举第一个字符串的所有子串,再分别将每个子串与剩下的n−1个字符串进行匹配,有n个子串,n−1个字符串,匹配一次的是O(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个字符串中最长的相同子串,\\若有多个满足条件的子串,输出字典序最小的。 多组测试用例,每组包括n个字符串,要找这n个字符串中最长的相同子串,若有多个满足条件的子串,输出字典序最小的。
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 2≤n≤4000,字符串长度m<=200Time limit:3000ms,Memory limit:32768kB
题解:
与 上 一 题 类 似 , 区 别 在 于 先 要 保 证 长 度 最 大 , 再 保 证 字 典 序 最 小 。 可 以 用 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;
}