单词背诵

P1381 单词背诵

我们发现,前后两个问题完全独立,我们先找出整个序列中共出现了多少个单词,扫一遍即可。

后面的问题就类似于逛画展了,我们只需要用尺取法解决。

英文字母当作下标太麻烦,所以用STL哈希一下。

时间复杂度线性。(刚开始还想着二分,后来发现直接求解就好了)。

#include<iostream>
#include<unordered_map>
#include<cstring>
using namespace std;
#define Ed for(int i=h[x];~i;i=ne[i])
#define Ls(i,l,r) for(int i=l;i<r;++i)
#define Rs(i,l,r) for(int i=l;i>r;--i)
#define Le(i,l,r) for(int i=l;i<=r;++i)
#define Re(i,l,r) for(int i=l;i>=r;--i)
#define L(i,l) for(int i=0;i<l;++i)
#define E(i,l) for(int i=1;i<=l;++i)
#define W(t) while(t--)
#define Wh while

const int N=100010,M=1010;
unordered_map<string,int>mp;
int cnt[M],n,m,a[N];
int calc(int mid){
    memset(cnt+1,0,n*4);
    int ans=N;
    int r=0,tot=0;
    E(l, m){
        Wh(r<m&&tot<mid)
            a[++r]&&!cnt[a[r]]++&&++tot;
        if(r==m&&tot<mid)break;
        ans=min(ans,r-l+1);
        !--cnt[a[l]]&&--tot;
    }
    return ans;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    #endif
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    E(i, n){
        string s;
        cin>>s;
        mp[s]=i;
    }
    cin>>m;
    E(i, m){
        string s;
        cin>>s;
        a[i]=mp.find(s)!=mp.end()?mp[s]:0;
    }
    int tot=0;
    E(i, m)
        a[i]&&!cnt[a[i]]++&&++tot;
    cout<<tot<<'\n'<<(tot?calc(tot):0);
    return 0;
}
posted @ 2023-09-25 14:58  wscqwq  阅读(4)  评论(0编辑  收藏  举报