解题思路
考虑把要背的单词与文章中的单词都通过
H
a
s
h
Hash
Hash函数化为
h
a
s
h
hash
hash值,然后直接就能求出最多包含的要背的单词数
m
a
x
n
maxn
maxn。
对于第二个问题,考虑尺取法:
- 初始化 l = r = m l=r=m l=r=m;(从0开始也是没问题的)
- 每次把 l l l向左移,如果是要背的单词就 n u m + + num++ num++
- 如果 n u m = = m a x n num==maxn num==maxn,就考虑r能不能向左移(不是要背的单词就能移),然后更新答案 a n s = m i n ( a n s , r − l ) ans=min(ans,r-l) ans=min(ans,r−l)最后取消 r r r位置上的单词,具体情况详见代码。。
代码
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int p=131,mod=1000007;
int n,m,a[1010],b[100010],v[2000000],use[2000000],vv[2000000],maxn,num,ans=2147483600,r;
string x;
int hash(string s)
{
int cnt=0;
for(int i=0;i<s.size();i++)
{
cnt=(cnt*p+s[i])%mod;
}
return cnt;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
cin>>x;
a[i]=hash(x);
v[a[i]]=1;
}
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
cin>>x;
b[i]=hash(x);
if(v[b[i]]&&!use[b[i]])
{
maxn++;
use[b[i]]=1;
}
}
if(maxn==0){
printf("0\n0");
return 0;
}
else printf("%d\n",maxn);
r=0;
for(int l=1;l<=m;l++)
{
while(num<maxn&&r<m)
{
r++;
if(v[b[r]])
{
if(vv[b[r]]==0)
num++;
vv[b[r]]++;
}
}
if(num==maxn)
{
while(!v[b[l]])
l++;
ans=min(ans,r-l+1);
if(vv[b[l]]>=1)
{
if(vv[b[l]]==1)
num--;
vv[b[l]]--;
}
}
}
printf("%d",ans);
}