• P2375 [NOI2014]动物园


    P2375 [NOI2014]动物园

    为什么复制题目连字体大小一块复制过来了(雾)

    我竟然会做NOI的题目辣~(≧▽≦)/~(看的题解

    总而言之,这是一道简单的KMP问题。题面简直是给没学过KMP的人看的(比如我)。

    我们发现,这个所谓的num数组和nxt有异曲同工之妙。但是我们对于不能重合这一块有一点问号。那我们先不管重不重合,先给他记录成重合的。

    于是在标记nxt时同时也可以把num标记。原理是,nxt记录的是该字符串相同的前缀字符个数,num[i]记录的是当前字符作为从0到i的子串内后缀与前缀相同的子串的子串的数目。我们发现,其实他就是num[j]+1,j就是nxt[i]!可以举几个例子模拟一下。

    这样一来查询的时候也很方便了。

    问题来了,怎么去重呢?如果j已经到i<<1的时候,我们将j挪到nxt[j]就好了,直到j<i/2。因为上面我们记录的num数组的特性,如果有重叠此时的值就相当于在nxt[j]的时候的没有重叠的串的num数。模拟一下也很好理解的。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define mod 1000000007 
    using namespace std;
    typedef long long ll;
    const int maxn=1e6+5;
    char a[maxn];
    int nxt[maxn],len,num[maxn];
    inline void getnxt()
    {
        int k=-1,j=0;
        nxt[0]=-1;
        while(j<len)
        {
            if(k==-1 or a[j]==a[k])nxt[++j]=++k,num[j]=num[k]+1;
            else k=nxt[k];
        }
    }
    inline void kmp()
    {
        int j=0,i=1;
        ll ans=1;
        while(i<len)
        {
            if(j==-1 or a[j]==a[i]){
                j++,i++;
                while((j<<1)>=(i+1))j=nxt[j];
                ans=(ans*(ll)(num[j]+1))%mod;
            }
            else j=nxt[j];
        }
        printf("%lld
    ",ans);
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%s",&a);
            len=strlen(a);
            memset(nxt,0,sizeof nxt);
            num[0]=0,num[1]=1;
            getnxt();
            kmp();
        }
        return 0;
    }
  • 相关阅读:
    python的thread模块作用
    Python2、3解释器inpurt()函数的区别
    python中的单例设计模式
    Python2、3解释器中字符串中的区别
    浏览器向服务器发送请求的请求头解析
    Python中输出函数print()的三个参数
    Python中四种交换两个变量的值的方法
    学习爬虫看着篇(基础篇)
    Python读写txt文件时的编码问题
    网页和自然语言处理中的字符问题(半角和全角)
  • 原文地址:https://www.cnblogs.com/BrotherHood/p/13142031.html
Copyright © 2020-2023  润新知