zoukankan      html  css  js  c++  java
  • 洛谷

    https://www.luogu.org/problemnew/show/P1381

    字符串匹配,用哈希总没有错的。
    然后就是尺取了,题目要求首先尽可能多覆盖,那么每次尾巴往后面长。
    一开始先找到第一个要的词汇。这个不多说。
    然后每次往后面长,遇到非法词汇就继续长。
    遇到合法的,就把头部所有合法的重复词和非法词都取出来。
    注意要特殊处理非法词。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    
    typedef unsigned long long ull;
    
    
    unordered_set<ull> dic;//要背的单词的词典
    unordered_map<ull,int> cnt;//当前区间要背单词的数量
    
    int n,m;
    ull get_hash(char *s) {
        ull res=0;
        for(int i=0; s[i]!=''; i++) {
            res=res*19260817+s[i];
        }
        return res;
    }
    
    char str[15];
    ull a[100005];
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in","r",stdin);
    #endif // Yinku
        scanf("%d",&n);
        for(int i=1; i<=n; i++) {
            scanf("%s",str);
            dic.insert(get_hash(str));
        }
        scanf("%d",&m);
        int cntv=0;
        int len=0;
        int head=1;//尺取区间的头
    
        int maxcnt=0;
        int maxcnt_len=0;
        for(int i=1; i<=m; i++) {
            scanf("%s",str);
            ull ha=get_hash(str);
            a[i]=ha;
            if(cnt.size()==0) {
                //刚刚开始处理,尺取区间里面没有有效单词
                if(!dic.count(ha)) {
                    //这个单词也是无效的,直接把head指向下一个位置
                    head++;
                } else {
                    //这个单词是有效的,包含进来
                    cnt[ha]++;
                    //head固定在这里了,新单词导致cntv上升
                    cntv++;
                    //第一个单词使得len也上升了
                    len++;
                    if(cntv>=maxcnt) {
                        if(cntv>maxcnt) {
                            maxcnt=cntv;
                            maxcnt_len=len;
                        } else {
                            maxcnt_len=min(maxcnt_len,len);
                        }
                    }
                }
            } else {
                //尺取区间的单词列表中至少有一个
                if(!dic.count(ha)) {
                    //就算没用但是可能会把后面连起来,记上
                    len++;
                } else {
                    //这个词是有用的
                    if(!cnt.count(ha)) {
                        //这个词没见过
                        cntv++;
                    }
                    cnt[ha]++;
                    len++;
                    while(!dic.count(a[head])||cnt[a[head]]>=2) {
                        //头部是非法词汇,或者头部是合法词汇,且至少重复了1次,把头部取出
                        if(dic.count(a[head]))
                            cnt[a[head]]--;
                        head++;
                        len--;
                    }
                    //现在头部必定是不重复的合法词汇,且至少有1个
                    if(cntv>=maxcnt) {
                        if(cntv>maxcnt) {
                            maxcnt=cntv;
                            maxcnt_len=len;
                        } else {
                            maxcnt_len=min(maxcnt_len,len);
                        }
                    }
                }
            }
        }
    
        printf("%d
    %d
    ",maxcnt,maxcnt_len);
    
        return 0;
    }
    
  • 相关阅读:
    left join 和 inner join 区别和优化
    认识位移操作符
    動態修改 XML 欄位
    (轉載)sql server xml字段的操作
    (轉)CSS 单行溢出文本显示省略号...的方法(兼容IE FF)
    (轉)Equal height boxes with CSS
    獲得瀏覽器顯示標簽的真實的長寬高
    轉:Jquery绑定img的click事件
    SqlLocalDB 的一些常用命令行
    转:css实现强制不换行/自动换行/强制换行
  • 原文地址:https://www.cnblogs.com/Yinku/p/11013780.html
Copyright © 2011-2022 走看看