Luogu-1381 单词背诵

先将n个单词插入哈希表,记录左右端点,每次右端点往后移动,读入一个新的单词并记录下它的哈希值,如果这个单词之前没出现过那么更新\(ans\)\(minl\),如果左端点的单词出现了不止一次则可以往右缩,从而保证长度最短。

#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read(){
    int ans=0,fh=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')
            fh=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
        ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
    return ans*fh;
}
typedef long long ll;
typedef unsigned long long ull;
const int maxn=1e5+100,maxm=1e3+100;
const ull base=131,P=1e6+3;
struct hash{
    int siz[P],cz[P];
    inline ull gethash(char *s){
        ull ans=0;
        for(int i=0,L=strlen(s);i<L;i++)
            ans=(ans*base+s[i])%P;
        return ans;
    }
//  inline void revise(char *s,int z){
//      ull x=gethash(s);
//      siz[x]+=z;
//  }
    inline void insert(char *s){
        ull x=gethash(s);
        cz[x]=1;
    }
//  inline int query(char *s){
//      ull x=gethash(x);
//      return siz[x];
//  }
    inline int find(char *s){
        ull x=gethash(s);
        if(!cz[x]) x=-1;
        return x;
    }
}h;
int n,a[maxn],m,ans,minl;
char s[maxm];
int main(){
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%s",s),h.insert(s);
    scanf("%d",&m);
    int l=0;
    for(int i=1;i<=m;i++){
        scanf("%s",s);
        int x=h.find(s);
        a[i]=x;
        if(~x){
            if(h.siz[x]==0) ans++,minl=i-l;
            h.siz[x]++;
            while(a[l+1]==-1||h.siz[a[l+1]]>1)
                l++,h.siz[a[l]]--,minl=min(minl,i-l);
        }
    }
    printf("%d\n%d\n",ans,minl);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/nianheng/p/9922569.html
今日推荐