zoukankan      html  css  js  c++  java
  • 0118模拟赛订正

    模拟赛还是要好好订正的....

    先说下第三题吧,毕竟前两道题过于鬼畜....

    起码这个题的题解还是我能接受的,虽然说考试时我还不会KMP...

    这道题要求对每一个前缀我们都要求一个最小得覆盖长度....

    那对于一个字符串S,设A是要求的答案,由于第一个字符和最后一个字符的限制,所以A一定是S的一个前缀和后缀,换句话说A一定是S中一个相等的前缀和后缀对应的字符串.

    而想到这就不难想到KMP的next数组,因为next的定义就是以i结尾的后缀与前缀的最大长度,显然我们要用到这个数组,之后我们思考ans[i](答案数组)的构成.

    存在一些性质,ans[i]要么等于i要么等于ans[next[i]]....

    至于证明嘛...:

    感觉和next数组的证明好像...

    我们假设k是答案,且k不是ans[next[i]]那显然[0,k]与[k,i]是相等的,而这显然也满足next数组的定义,则k、应该是next[i]最大的与此矛盾...

    之后我们就该考虑这样判定next[i]之间的区间能不能被next[i]的答案覆盖(也就是绿色的部分)...

    这个我们就要记录一个答案数组last[i]表示到目前为止,答案长度为i覆盖最远到哪.

    我们可以通过判定last[ans[next[i]]]与i-next[i]的关系来得到。

    last[ans[next[i]]]表示的意义是next[i]的答案覆盖到的最远距离,如果他超过i-next[i],由于他已经覆盖了前面的的[0,next[i]]所以后面的[next[i],i]它一定能覆盖...

    而i-next就是绿色区间的右段点,由于ans[next[i]]一定能覆盖[0,next[i]]所以本质还是判断next[i]的答案能不能覆盖绿色的区间...

    至于代码就很短,不过这个题是真的不错....

    #include<bits/stdc++.h>
    using namespace std;
    const int N=200010;
    int last[N],next[N],ans[N],n;//last[j]数组的含义是里当前i最近的答案为j的覆盖到的距离. 
    char str[N];
    inline int read()
    {
        int x=0,ff=1;
        char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*ff;
    }
    inline void KMP()
    {
        next[1]=0;
        ans[1]=1;
        last[1]=1;
        for(int i=2,j=0;i<=n;++i)
        {
            while(j>0&&str[i]!=str[j+1]) j=next[j];
            if(str[i]==str[j+1]) ++j;
            next[i]=j;
            if(next[i]==0) ans[i]=i;
            else 
            {
                if(last[ans[next[i]]]>=i-next[i]) ans[i]=ans[next[i]];
                else ans[i]=i;
            }
            last[ans[i]]=i;
        }
    }
    int main()
    {
        freopen("cover.in","r",stdin);
        freopen("cover.out","w",stdout);
        scanf("%s",str+1);
        n=strlen(str+1);
        KMP();
        for(int i=1;i<=n;++i) printf("%d ",ans[i]);
        return 0;
    }
  • 相关阅读:
    C语言提供的位运算符
    JAVA反射改动常量,以及其局限
    直击中关村创业大街,新街头霸王来了
    bind() to 0.0.0.0:80 failed (98: Address already in use)
    Eclipse 快捷方式 指定 固定 workspace
    C++对象模型——Inline Functions(第四章)
    eclipse中安装freemarker插件及ftl使用freemarker编辑器
    迷茫了好一阵决定做WEB前端
    ios代理的使用,正向传值,逆向传值
    easyUI Tab href,content差别
  • 原文地址:https://www.cnblogs.com/gcfer/p/12214780.html
Copyright © 2011-2022 走看看