• BZOJ 1729: [Usaco2005 dec]Cow Patterns 牛的模式匹配


    Description

        约翰的N(1≤N≤100000)只奶牛中出现了K(1≤K≤25000)只爱惹麻烦的坏蛋.奶牛们按一定的顺序排队的时候,这些坏蛋总会站在一起.为了找出这些坏蛋,约翰让他的奶牛排好队进入牛棚,同时需要你的慧眼来识别坏蛋,为了区分,约翰给所有奶牛都发了号牌,上面写着一个1..S(1≤S≤25)之间的数字.虽然这不是一个完美的方法,但也能起一点作用.现在,约翰已经不记得坏蛋们的具体号码.但是凭他的记忆,他给出一个“模式串”.原坏蛋的号码如果相同,模式串中他们的号码依然相同.模式串中坏蛋们之间号码的大小关系也与原号码相同的.比如,对于这样一个模式串:1,4,4,3,,2,1 。原来的6只坏蛋,排最前面的与排最后的号码相同(尽管不一定是1),而且他们的号码在团伙中是最小的.第2,3位置的坏蛋,他们的号码也相同(不一定是4),且是坏蛋团伙中最大的.    现在所有奶牛排成队列,号码依次是这样:    5,6,2,10,10,7,3,2,9存在子串2,10,10,7,3,2,满足模式串的相同关系和大小关系,所以这就是坏蛋团伙, 请找出K个坏蛋的困伙的所有可能性.

    Input

        第1行输入三个整数N,K,S.接下来N行每行输入一只牛的号码.接下来K行每行输入一个模式串的号码.

    Output

        第1行输出一个整数B.接下来B行,每行一个整数,表示一种可能下的坏蛋团伙的起始位置.

    题解:

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
     
    //by zrt
    //problem:
    using namespace std;
    typedef long long LL;
    const int inf(0x3f3f3f3f);
    const double eps(1e-9);
    int n,k,s;int aa[100005][26],bb[100005][26];int a[100005],b[100005];
    bool cmp(int j,int i,int c1,int c2){//b 0...j | a i-j..i
        int sum1=0,sum2=0;
        for(int k=1;k<c1;k++){
            sum1+=j?bb[j-1][k]:0;
        }
        for(int k=1;k<c2;k++){
            sum2+=(i?aa[i-1][k]:0)-((i-j)?aa[i-j-1][k]:0);
        }
        return sum1==sum2&&(j?bb[j-1][c1]:0)==((i?aa[i-1][c2]:0)-((i-j)?aa[i-j-1][c2]:0));
    }
    bool cmpp(int j,int i,int c1,int c2){//b 0...j |b i-j..i
        int sum1=0,sum2=0;
        for(int k=1;k<c1;k++){
            sum1+=j?bb[j-1][k]:0;
        }
        for(int k=1;k<c2;k++){
            sum2+=(i?bb[i-1][k]:0)-((i-j)?bb[i-j-1][k]:0);
        }
        return sum1==sum2&&(j?bb[j-1][c1]:0)==((i?bb[i-1][c2]:0)-((i-j)?bb[i-j-1][c2]:0));
    }
    int nxt[100005];
     
    void mk_pre(){
        for(int i=0;i<n;i++) {
            if(i)for(int j=1;j<=s;j++) aa[i][j]=aa[i-1][j];
            aa[i][a[i]]++;
        }
        for(int i=0;i<k;i++) {
            if(i)for(int j=1;j<=s;j++) bb[i][j]=bb[i-1][j];
            bb[i][b[i]]++;
        }
    }
    void mk(){
        int j=-1;
        nxt[0]=-1;
        for(int i=1;i<k;i++){
            while(~j&&!cmpp(j+1,i,b[j+1],b[i])) j=nxt[j];
            if(cmpp(j+1,i,b[j+1],b[i])) j++;
            nxt[i]=j;
        }
    }
     
    int ans[100005],top;
    int main(){
        #ifdef LOCAL
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
        #endif
        scanf("%d%d%d",&n,&k,&s);
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
        }
        for(int i=0;i<k;i++){
            scanf("%d",&b[i]);
        }
        mk_pre();// qianzhuihe
        mk();
        int j=-1;
        for(int i=0;i<n;i++){
            while(~j&&!cmp(j+1,i,b[j+1],a[i])) j=nxt[j];
            if(cmp(j+1,i,b[j+1],a[i])) j++;
            if(j==k-1){
                ans[top++]=i-j+1;
                j=nxt[j];
            }
        }
        printf("%d
    ",top);
        for(int i=0;i<top;i++){
            printf("%d
    ",ans[i]);
        }
        return 0;
    }
  • 相关阅读:
    css
    css加号波浪号
    C++对象池
    C++11 智能指针
    C++内存泄漏检测(调试工具)
    JSONP是个嘛玩意?解决跨域问题?
    使用django + KindEditor 开发个人博客系统
    前端文本框插件KindEditor
    jQuery AJAX
    Django ModelForm表单验证
  • 原文地址:https://www.cnblogs.com/zrts/p/bzoj1729.html
Copyright © 2020-2023  润新知