• bzoj3620 似乎在梦中见过的样子


    Description

    “Madoka,不要相信 QB!”伴随着 Homura 的失望地喊叫,Madoka 与 QB 签订了契约.
    这是 Modoka 的一个噩梦,也同时是上个轮回中所发生的事.为了使这一次 Madoka 不再与 QB签订契约,Homura 决定在刚到学校的第一天就解决 QB.然而,QB 也是有许多替身的(但在第八话中的剧情显示它也有可能是无限重生的),不过,意志坚定的 Homura 是不会放弃的——她决定
    消灭所有可能是 QB 的东西.现在,她已感受到附近的状态,并且把它转化为一个长度为 n 的字符串交给了学 OI 的你.
    现在你从她的话中知道 , 所有形似于 A+B+A 的字串都是 QB 或它的替身 , 且len(A)>=k,len(B)>=1 (位置不同其他性质相同的子串算不同子串,位置相同但拆分不同的子串算同一子串),然后你必须尽快告诉 Homura 这个答案——QB 以及它的替身的数量.

    Input

    第一行一个字符串,第二行一个数 k

    Output

    仅一行一个数 ans,表示 QB 以及它的替身的数量

    Sample Input

    【样例输入 1】
    aaaaa
    1
    【样例输入 2】
    abcabcabc
    2

    Sample Output

    【样例输出 1】
    6

    【样例输出 2】
    8

    HINT 

    对于 100%的数据:n<=15000 , k<=100,且字符集为所有小写字母

    正解:$kmp$算法。

    $NOI2014$动物园的弱化版。。

    首先这题正解好像就是$O(n^{2})$的算法,于是直接枚举合法字符串的左端点,从左端点开始的字串跑一遍$kmp$,注意这道题的匹配条件有一个限制,那就是前缀与后缀匹配的长度小于串长$/2$。于是我们另外开一个$nt$数组,记录长度小于$n/2$的前缀和后缀的匹配,如果失配就直接跳$next$。具体操作可以看代码。。

     1 //It is made by wfj_2048~
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <cstring>
     5 #include <cstdlib>
     6 #include <cstdio>
     7 #include <vector>
     8 #include <cmath>
     9 #include <queue>
    10 #include <stack>
    11 #include <map>
    12 #include <set>
    13 #define inf (1<<30)
    14 #define N (200010)
    15 #define il inline
    16 #define RG register
    17 #define ll long long
    18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    19 
    20 using namespace std;
    21 
    22 int nxt[N],nt[N],k,len,ans;
    23 char s[N],c[N];
    24 
    25 il int gi(){
    26     RG int x=0,q=1; RG char ch=getchar();
    27     while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    28     if (ch=='-') q=-1,ch=getchar();
    29     while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
    30     return q*x;
    31 }
    32 
    33 il void work(){
    34     scanf("%s",s+1),len=strlen(s+1),k=gi();
    35     for (RG int p=1;p<=len;++p){
    36     RG int l=0; for (RG int i=p;i<=len;++i) c[++l]=s[i];
    37     for (RG int i=2,j;i<=l;++i){
    38         j=nxt[i-1]; while (j && c[j+1]!=c[i]) j=nxt[j];
    39         if (c[j+1]==c[i]) nxt[i]=j+1; else nxt[i]=0; j=nt[i-1];
    40         while (j && (c[j+1]!=c[i] || j>((i-1)>>1)-1)) j=nxt[j];
    41         if (c[j+1]==c[i] && j<=((i-1)>>1)-1) nt[i]=j+1; else nt[i]=0;
    42         if (nt[i]>=k) ++ans;
    43     }
    44     }
    45     printf("%d
    ",ans); return;
    46 }
    47 
    48 int main(){
    49     File("3620");
    50     work();
    51     return 0;
    52 }
  • 相关阅读:
    [USACO08FEB]酒店Hotel 线段树 BZOJ 1593
    有趣的数 zoj 月赛
    [ZJOI2008]生日聚会 BZOJ1037 dp
    借教室 差分+二分答案
    HackerRank
    旅行计划 记忆化搜索
    灾后重建 Floyd
    [USACO10OCT]湖计数Lake Counting 联通块
    [TJOI2013]循环格 费用流 BZOJ3171
    高斯消元
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7128087.html
Copyright © 2020-2023  润新知