zoukankan      html  css  js  c++  java
  • [NOI2014]动物园(KMP)

    题意

    题解

    因为,一直用j=nxt[j]来遍历,可以遍历前i个字符所有相等的前后缀长度,所以有一个暴力的想法,就是对于每一个长度,开始遍历,记录长度小于i/2的相等的前后缀数量,最后累加即可。

    但显然超时了。

    换一种思路,其实我们要的只是长度小于i/2的相等的前后缀数量。

    然后我们可以利用KMP的方法求出一个新的nxt数组,代表前i个数中最大的,且长度不超过i/2的相等的前后缀的长度。

    对于每一个长度i,我们在预处理出前i个字符中前缀等于后缀的数量num[i]。那么每一个长度对答案的贡献为num[新nxt[i]]+1;

     1 #include<iostream>
     2 #include<cmath>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<algorithm>
     6 using namespace std;
     7 const int N=1001000;
     8 const int mod=1e9+7;
     9 int t;
    10 char s[N];
    11 int num[N],nxt[N];
    12 int main(){
    13     scanf("%d",&t);
    14     while(t--){
    15         scanf("%s",s+1);
    16         int len=strlen(s+1);
    17         nxt[1]=0;
    18         num[1]=1;
    19         num[0]=0;
    20         for(int i=2,j=0;i<=len;i++){
    21             while(j&&s[j+1]!=s[i])j=nxt[j];
    22             if(s[i]==s[j+1])j++;
    23             nxt[i]=j; 
    24             num[i]=num[j]+1;
    25         }
    26         long long ans=1;
    27         for(int i=2,j=0;i<=len;i++){
    28             while(j&&s[i]!=s[j+1])j=nxt[j];
    29             if(s[j+1]==s[i])j++;
    30             while(j*2>i)j=nxt[j];
    31             ans=(ans*(long long)(num[j]+1))%mod;
    32         }
    33         printf("%lld
    ",ans);
    34     } 
    35     return 0;
    36 } 
  • 相关阅读:
    python学习笔记——拾
    python学习笔记——玖
    Python 实现栈与队列
    Vijos1774 机器翻译 [模拟]
    Vijos1788 第K大 [模拟]
    Python 序列求和
    HDU 2102 A计划 DFS与BFS两种写法 [搜索]
    Python 多组输入
    Python 文件读写
    HDU 2068 RPG错排 [错排公式]
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/9530191.html
Copyright © 2011-2022 走看看