思路
首先把需要背诵的单词存入 h a s h hash hash 表。
然后我们要把单词表里的单词先扫一遍,统计出最坏长度的答案。
然后用尺取法,不断向右移动 r r r, 当当前长度已经可以得到最坏长度的答案,就更行长度,然后把l向右移到一个单词出列(遇到相同单词继续移)。
注意:单词表中的单词可能不需要背诵!
代码
#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
int wz[100010],t[100010],t2[100010];
unsigned long long js;
string s[100010];
int n,m,ans,ansjl;
struct node
{
unsigned long long hash1,hash2;
long long bj;
}a[100010];
bool cmp(const node&df,const node&df2)
{
return df.hash1<df2.hash1;
}
int main()
{
cin>>n;
for(int i=1; i<=n; i++)
{
cin>>s[i];
a[i].bj=i;
int lon=s[i].size();
for(int j=0; j<=lon-1; j++)
a[i].hash1=a[i].hash1*131ull+(s[i][j]-43);
}
sort(a+1,a+1+n,cmp);
cin>>m;
for(int i=1; i<=m; i++)
{
cin>>s[i];
int lon=s[i].size();
wz[i]=-1,js=0; //初始化-1,如果出现主义中的状况就可直接判断
for(int j=0; j<=lon-1; j++)
js=js*131ull+(s[i][j]-43);
int l=1,r=n,mid=0;
while(l<=r)
{
mid=(l+r)>>1;
if(js<a[mid].hash1)
r=mid-1;
else if(js>a[mid].hash1)
l=mid+1;
else
{
wz[i]=a[mid].bj;
break;
}
}
if(t[wz[i]]==0&&!(wz[i]==-1))
{
t[wz[i]]=1;
ans++;
}
}
cout<<ans;
ansjl=m;
int l=1,ans2=0;
for(int r=1; r<=m; r++)
{
if(wz[r]!=-1)
{
if(t2[wz[r]]==0)
ans2++;
t2[wz[r]]++;
if(wz[l]!=-1)
{
while(l<=r&&ans2==ans)
{
t2[wz[l]]--;
if(t2[wz[l]]==0)
{
ansjl=min(ansjl,r-l+1);
ans2--;
}
l++;
}
}
}
}
cout<<endl<<ansjl;
return 0;
}