zoukankan      html  css  js  c++  java
  • 洛谷2375 BZOJ 3670动物园题解

    题目链接

    洛谷链接

    我们发现题目要我们求的num[i]东西本质上其实是

    求有多少以i结尾的非前缀且能与前缀匹配的字符串,而且要求字符串长度小于(i/2)

    我们先不考虑字符串长度的限制,看所有以i结尾的非前缀且能与前缀匹配的字符串如何计数

    考虑到KMP算法的next数组求解的过程,大家应该都想到i结尾的非前缀且能与前缀匹配的字符串的总数就是next[i]跳到0的所跳的次数

    为什么是这样的呢?

    如上图所示,其中绿色的串与红色的串是匹配的,若还要寻找匹配的串

    不难发现所有以红色结尾处结尾所能匹配的串都是满足要求的

    从上面的图不难发现以上结论是对的

    具体求解时,我们先求一遍next数组,若next[i]为0,则不存在这样的字符串,如果大于0,则令num[i]=dep[next[i]]+1

    但是我们还要考虑长度小于i/2这一个限制

    一个朴素的想法就是next不停跳知道小于i/2为止,但这样复杂度是nlogn,TLE

    所以我们要在做一遍魔改版KMP,求的是i结尾的非前缀且能与前缀匹配而且长度小于i/2的最长字符串

    num[i]=dep[next2[i]]+1

    魔改版KMP的求解过程与KMP类似,只是加了一句while(next[j]>i/2) j=next[j]

    附上代码

    # include<iostream>
    # include<algorithm>
    # include<cstring>
    # include<cmath>
    # include<cstdio>
    const int mod = 1e9 + 7 ;
    const int mn = 1100005;
    int n,ans,N;
    char s[mn];
    int nxt[mn],dep[mn];
    int main()
    {
        int tmp;
        scanf("%d",&n);
        while(n--)
        {
            ans=1;
            scanf("%s",s+1);
            N=strlen(s+1);
            nxt[1]=0;
            dep[0]=0,dep[1]=1;
            for(int i=2,j=0;i<=N;i++)
            {
                while(j>0 && s[i]!=s[j+1]) j=nxt[j];
                if(s[i]==s[j+1]) j++;
                nxt[i]=j;
                dep[i]=dep[j]+1;
            }
            /*for(int i=1;i<=N;i++)
            printf("%d ",nxt[i]);*/
            for(int i=2,j=0;i<=N;i++)
            {
                 while(j>0 && s[i]!=s[j+1]) j=nxt[j];
                 if(s[i]==s[j+1]) j++;
                 while(j>i/2) j=nxt[j];
                 ans=1ll*ans*(dep[j]+1)%mod;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    python之turtle画蚊香
    day08:多表查询
    day07:内置函数
    day06:基础查询
    day05:Navicat 图形化客户端的基本使用
    day04:MySQL数据库表的基本命令
    day03:MySQL数据库的使用
    day02:MySQL数据库的安装
    day01:数据库和SQL概述
    51单片机学习笔记(清翔版)(13)——LED点阵、74HC595
  • 原文地址:https://www.cnblogs.com/logeadd/p/9318315.html
Copyright © 2011-2022 走看看