zoukankan      html  css  js  c++  java
  • 3670: [Noi2014]动物园

    题目链接

    题意:给n个字符串,求出每个字符串的num值,加1后相乘。num[i]表示1~i中,有多少没有重叠的公共前缀后缀。

    分析:

    kmp中p数组表示最大的公共前缀后缀。设一cnt数组,表示1~i中有多少公共前缀后缀(包括重叠的),那么cnt[1]=1,(自己是自己的公共前后缀)。

    那么:cnt[i]=cnt[p[i]]+1:因为1~p[i]与i-p[i]+1~i是相等的,所以1~p[i]的公共前后缀一定被包含在1~i中,且字符串1~i也是自己的公共前后缀,所以再+1

    预处理出cnt数组后,那么对于1~i找到他的最大的且长度不超过i/2的公共前后缀,就是答案。

    code

     1 #include<cstdio>
     2 #include<cstring>
     3 
     4 const int N = 1000100;
     5 const int mod = 1e9+7;
     6 
     7 char w[N];
     8 int n,C,p[N],cnt[N];
     9 
    10 void work() {
    11     int k,ans;
    12     p[1] = 0; 
    13     cnt[1] = 1;
    14     for (int i=2; i<=n; ++i) {
    15         k = p[i-1];
    16         while (k && w[i]!=w[k+1]) k = p[k];
    17         if (w[i] == w[k+1]) k++;
    18         p[i] = k;
    19         cnt[i] = cnt[k] + 1;
    20     }
    21     k = 0,ans = 1;
    22     for (int i=1; i<=n; ++i) {
    23         while (k && w[i]!=w[k+1]) k = p[k];//这次求的k满足<i/2 
    24         if (w[i]==w[k+1]) k++;
    25         //k = p[i]; //直接赋值超时,第一次求的k可能是远大于i/2的 
    26         while (k > (i/2)) k = p[k]; // 这次的k为下次使用,不会远大于i/2 
    27         ans = (1ll * ans * (cnt[k]+1)) % mod; // num[i] = cnt[k] + 1
    28     }
    29     printf("%d
    ",ans);
    30 }
    31 int main () {
    32     scanf("%d",&C);
    33     while (C--) {
    34         scanf("%s",w+1);
    35         n = strlen(w+1);
    36         work();
    37     }
    38     return 0;
    39 }
  • 相关阅读:
    所谓经济现象
    高旻寺德林老和尚开示
    3Delight NSI: A Streamable Render API
    Play vue.js with constant value in SailsJS
    天魔心法之——识人篇
    对国内IoT的展望
    对国内AR产业的预言
    简评某中国工程师嫌疑窃取苹果自动驾驶技术
    评估人类的金三角模型
    Odoo 进销存报表现已开源
  • 原文地址:https://www.cnblogs.com/mjtcn/p/8628711.html
Copyright © 2011-2022 走看看