zoukankan      html  css  js  c++  java
  • 【洛谷P3435】OKRPeriods of Words【KMP】

    题目大意:

    题目链接:https://www.luogu.org/problemnew/show/P3435
    求一个字符串“前缀的前缀”的长度和。


    思路:

    “前缀的前缀”。。。难道不像next数组吗?
    首先先求出一个正常的next数组,之后很容易发现,next[next[i]]也是i的一个前缀,那么就很容易了。对于每一个i,求出大于0的最小的j=next[next[next[next[......i]]]],然后长度为i的答案就是ij
    之后考虑优化。很容易发现,next数组的递归次数太多了,需要减少。那么就每次求出j时,优化next[i]=j(因为其他都没用了,反正最后都要跳到j),那么当以后的next[next[...k]]=i时,就可以直接跳到j了。


    代码:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    int len,j,next[1000101];
    long long sum;
    char s[1000101];
    
    int main()
    {
        scanf("%d",&len);
        cin>>s;
        j=0;
        for (int i=1;i<len;i++)  //求next数组
        {
            while (j&&s[i]!=s[j]) j=next[j];
            if (s[i]==s[j]) j++;
            next[i+1]=j;
        }
        for (int i=1;i<=len;i++)
        {
            j=i;
            while (j&&next[j]) j=next[j];
            if (next[i]) next[i]=j;  //优化,减少次数
            sum+=(long long)(i-j);
        }
        cout<<sum;
        return 0;
    }
  • 相关阅读:
    HDU 树型dp
    NOIP模拟 Math
    HTML5本地存储LocalStorage和sessionStorage
    数据结构与算法第一章答案
    堆和队列的应用之——简单计算器
    HITCS-LAB1 Linux 下C工具的应用
    cs:app 第二章homework(已完结)
    vim使用小结(1)
    学术英语写作(1)
    linux基础(2)
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998713.html
Copyright © 2011-2022 走看看