zoukankan      html  css  js  c++  java
  • 【题解】洛谷P3435 [POI2006] OKR-Periods of Words(KMP)

    洛谷P3435:https://www.luogu.org/problemnew/show/P3435

    思路

    来自Kamijoulndex大佬的解释

    先把题面转成人话:

    对于给定串的每个前缀i,求最长的,使这个字符串重复两遍能覆盖原前缀i的前缀(就是前缀i的一个前缀),求所有的这些“前缀的前缀”的长度和

    因为前缀i长度为p[i]的前缀和后缀相同

    这说明:如果i有一个公共前后缀长度为j,那么这个前缀i就有一个周期为i-j

    显然 图中蓝色线段是黑色线段的一个周期

    那么我们先预处理出P数组

    对于每个前缀i 我们令j=i 在j>0是不断查询j=p[j] 使j变得越来越小

    则周期i-j就会越来越大

    最后ans+=i-j

    感谢dalao的思路orzorz

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define maxn 1000010
    char a[maxn];
    int p[maxn];
    int len,j;
    long long ans;
    int main()
    { 
        scanf("%d",&len);
        scanf("%s",a+1);
        for(int i=2;i<=len;i++)//常规KMP 
        {
            while(j&&a[j+1]!=a[i]) j=p[j];
            if(a[j+1]==a[i]) j++;
            p[i]=j;    
        }    
        for(int i=1;i<=len;i++)//对每个前缀 
        {
            j=i;//令j=i 
            while(p[j]) j=p[j];//不断缩小j 
            if(p[i]!=0) p[i]=j;//记忆化 
            ans+=i-j;//累计ans 
        }
        printf("%lld",ans);
    }
  • 相关阅读:
    JavaScript 焦点事件
    在虚拟机里面运行java程序
    CentOS 7 命令
    修改和删除
    查询语句,查询指定的字段,带条件查询,排序查询
    Redis系列之-缓存的使用和优化
    Redis系列之-Redis-Sentinel
    Redis系列之主从复制原理与优化
    Redis系列之-使用常见问题
    Redis系列之-持久化
  • 原文地址:https://www.cnblogs.com/BrokenString/p/9782261.html
Copyright © 2011-2022 走看看