• BZOJ_3620_似乎在梦中见过的样子_KMP


    BZOJ_3620_似乎在梦中见过的样子_KMP

    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,且字符集为所有小写字母


    15000跑$O(n^2)$,绝了。

    枚举左端点,考虑当前后缀的所有前缀,kmp求出nxt的同时找到与j匹配的位置k。

    令rr[j]表示符合到i距离大于等于K的最小位置(如果没有这样的位置则为inf)

    那么只需要判断这个是否小于等于(i+j)/2即可。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 15050
    char w[N];
    int K,n,ans,nxt[N],rr[N];
    int main() {
        scanf("%s%d",w+1,&K);
        int i;
        n=strlen(w+1);
        for(i=1;i<=n;i++) {
            int j,k=i-1;
            nxt[k+1]=i-1; rr[k+1]=i;
            for(j=i+1;j<=n;j++) {
                while(k!=i-1&&w[k+1]!=w[j]) k=nxt[k];
                if(w[k+1]==w[j]) nxt[j]=++k;
                else nxt[j]=i-1;
                if(k<i+K-1) rr[j]=j;
                else rr[j]=rr[k];
                ans+=rr[j]<((i+j)>>1);
            }
        }
        printf("%d
    ",ans);
    }
    
  • 相关阅读:
    four day (linux基础学习1)
    three day(网络基础)
    two day(操作系统)
    Oldboy One day(计算机基础)
    mybatis调用存储过程
    调用jiathis分享接口
    汉字转换拼音工具类
    Ajax前后台交互 返回普通格式和JSON格式
    Bootstrap与EasyUI入门
    MD5,sha1加密工具类
  • 原文地址:https://www.cnblogs.com/suika/p/9152906.html
Copyright © 2020-2023  润新知