第一题 漏洞和补丁
背景
ICG模拟赛开始了!
由FF博士带领的团队要开始准备ICG模拟赛了,但他们发现机房的电脑有很多漏洞。
为了修补漏洞,只有下载各种补丁。 但是由于这些漏洞太过久远,不一定能找到能够修复漏洞的补丁。
以下有n个漏洞和m个补丁,用字符串表示。
若其中一个漏洞被一个补丁包含或包含一个补丁则认为这是一个可以被修复的漏洞。
(不区分大小写,一个补丁可以修复多个漏洞,一个漏洞只能被修复一次)
输出能被修复的漏洞总数。
输入格式:
第一行,两个整数n,m;
第2行到第N+1行,表示漏洞的名称;
接下来M行表示能下载到的各个补丁的名称。
输出格式
1个整数,表示能被修复的漏洞总数。
输入样例
3 3
Abc
DGFYJJa
ICG2010
aBCd
YHDajfje
ICG
输出样例
2
样例解释:
漏洞是
Abc
DGFYJJa
ICG2010
补丁是:
aBCd
YHDajfje
IcG
其中1号漏洞Abc被aBCd包含,可修复。3号漏洞ICG2010包含IcG.所以有2个漏洞可以被修复。
(可能会出现同名的补丁或漏洞。)
数据范围:
对于每个给出的漏洞和补丁,长度不超过256;
对于100%的数据,m,n<=100
傻了,写了kmp,浪费了时间。
因为n和m写反而wa80,悲剧。
注意一个漏洞只能修复一次。
#include <cstdio>
#include <cstring>
long next[300];
void next_init(char a[300])
{
long k = 0;
long j = 1;
long lena = strlen(a+1);
while (j < lena+1)
{
if (k==0 || a[j]==a[k])
{
j ++; k ++;
next[j] = k;
}
else
k = next[k];
}
}
bool kmp(char a[300],char b[300])
{
long i = 1;
long j = 1;
long lena = strlen(a+1);
long lenb = strlen(b+1);
while (i<lena+1 && j<lenb+1)
{
if (j==0 || a[i]==b[j])
{
i ++; j ++;
}
else
j = next[j];
if (j > lenb)
{
return true;
}
}
return false;
}
bool hash[110];
char a[110][300];
char b[110][300];
int main()
{
freopen("patch.in","r",stdin);
freopen("patch.out","w",stdout);
long n,m;
scanf("%ld%ld",&n,&m);
for (long i=1;i<n+1;i++)
{
scanf("%s",a[i]+1);
long tmp = 0;
while (a[i][++tmp])
if (a[i][tmp]<='Z'&&a[i][tmp]>='A')
a[i][tmp] += 32;
}
for (long i=1;i<m+1;i++)
{
scanf("%s",b[i]+1);
long tmp = 0;
while (b[i][++tmp])
if (b[i][tmp]<='Z'&&b[i][tmp]>='A')
b[i][tmp] += 32;
}
for (long i=1;i<m+1;i++)
{
next_init(b[i]);
for (long j=1;j<m+1;j++)
{
if (!hash[j])
if (kmp(a[j],b[i]))
hash[j] = true;
}
}
for (long i=1;i<n+1;i++)
{
if (!hash[i])
{
next_init(a[i]);
for (long j=1;j<m+1;j++)
if (kmp(b[j],a[i]))
hash[i] = true;
}
}
long ans = 0;
for (long i=1;i<n+1;i++)
if (hash[i])
ans ++;
printf("%ld",ans);
return 0;
}