题目链接:点击此处
题目大意:
给出n个字符串,记为 S 1 , S 2 , S 3 . . . S n S_1,S_2,S_3...Sn S1,S2,S3...Sn 找到最大的 i i i ,使之满足:存在 j < i j<i j<i 且 S j S_j Sj 不是 S i S_i Si 的子串
题目分析:
先讲一个名叫
s
t
r
s
t
r
(
s
t
r
1
,
s
t
r
2
)
strstr(str1,str2)
strstr(str1,str2) 的函数,其作用是判断字符串str2是否是str1的子串,如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL。一般认为这个函数的复杂度与kmp相同,但是极个别情况这个函数的复杂度会被卡到
O
(
n
2
)
O(n^2)
O(n2)
直接枚举
S
i
,
S
j
S_i,S_j
Si,Sj 复杂度为
O
(
n
2
)
O(n^2)
O(n2) 加上一点细节处理减小复杂度可以过
这里讲一种
O
(
n
)
O(n)
O(n) 的尺取做法:
如果
S
l
S_l
Sl 是
S
r
S_r
Sr 的字串显然可以让
l
l
l ++ 因为只需要存在一个
l
<
r
l<r
l<r 且
S
l
S_l
Sl 不是
S
r
S_r
Sr 的子串即可而不是需要不存在
S
r
S_r
Sr 的子串
如果
S
l
S_l
Sl 不是
S
r
S_r
Sr 的字串使,那么此时的
r
r
r 就是我们当前的局部最优解用
a
n
s
ans
ans 记录即可
其余细节见代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
int read()//习惯用快读
{
int res = 0,flag = 1;
char ch = getchar();
while(ch<'0' || ch>'9')
{
if(ch == '-') flag = -1;
ch = getchar();
}
while(ch>='0' && ch<='9')
{
res = (res<<3)+(res<<1)+(ch^48);//res*10+ch-'0';
ch = getchar();
}
return res*flag;
}
const int maxn = 2e3+5;
char s[505][maxn];
int main()
{
int t = read(),cas = 0;
while(t--)
{
int n = read(),ans = -1;
for(register int i = 1;i <= n;++i)
scanf("%s",s[i]);
int l = 1;
for(int r = 2;r <= n;r++)
{
while(l < r)
{
if(strstr(s[r],s[l])) l++;
else {
ans = r;
break;
}
}
}
printf("Case #%d: %d\n",++cas,ans);
}
return 0;
}