首页 > 其他 > 详细

CF432D Prefixes and Suffixes

时间:2020-01-02 20:48:04      阅读:80      评论:0      收藏:0      [点我收藏+]

CF432D Prefixes and Suffixes

题意

给你一个长度为n的长字符串,“完美子串”既是它的前缀也是它的后缀,求“完美子串”的个数且统计这些子串的在长字符串中出现的次数

分析

求出nex数组 , 在求出每个前缀出现的次数 , 从nex[n] 往下走就行了

其实这道题是 , KMP 求每个前缀出现次数的模板题

求前缀出现次数的写法

    for(int i = 1 ; i <= n ; ++i) num[i]++;
    for(int i = n ; i >= 1 ; --i) num[nex[i]] += num[i];

这个的意思是 , 首先长度为 i 的前缀有大自己 , 也就是 1

在考虑 长的为 i 的前缀可以把它的次数转移给谁呢?前缀本身已经计算过了, 接下来只要计算不是前缀本身的 , nex[i] 是他的最长公共前后缀,也就是有一个以 i 为右端点, 长为 nex[i] 的子串 和前缀相同 , 所以 i 出现多少次 , nex[i] 的前缀也应该加上他出现的次数

    for(int i = 1 ; i <= n ; ++i) num[nex[i]]++;
    for(int i = n ; i >= 1 ; --i) num[nex[i]] += num[i];
    for(int i = 1 ; i <= n ; ++i) num[i]++;

这个的意思是 , 先刨除他本身 ,再在最后加上;

个人推荐第一种好理解 , 还短

上本题代码

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 1e5+100;
int n;
int nex[N] , num[N] , cnt[N];
char c[N];
int main()
{
    scanf("%s",c+1); n = strlen(c+1);
    for(int i = 2 , k = 0 ; i <= n ; ++i)
    {
        while(k && c[i] != c[k + 1]) k = nex[k];
        if(c[i] == c[k + 1]) k++; nex[i] = k;
    }
    int tot = 0 , k = nex[n];
    while(k) cnt[++tot] = k , k = nex[k];
    printf("%d\n" , tot + 1);
//  for(int i = 1 ; i <= n ; ++i) num[i]++;
//  for(int i = n ; i >= 1 ; --i) num[nex[i]] += num[i];
    
    for(int i = 1 ; i <= n ; ++i) num[nex[i]]++;
    for(int i = n ; i >= 1 ; --i) num[nex[i]] += num[i];
    for(int i = 1 ; i <= n ; ++i) num[i]++;
    for(int i = tot ; i >= 1 ; --i)
        printf("%d %d\n" , cnt[i] , num[cnt[i]]);
    printf("%d 1\n" , n);
    return 0;
}

CF432D Prefixes and Suffixes

原文:https://www.cnblogs.com/R-Q-R-Q/p/12141659.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!