[codeforces/gym/100431/E]KMP关于border的理解

题目链接:http://codeforces.com/gym/100431/

考虑到对于一个串β,能cover它的最短的α必然是它的border的某个前缀,或者是这个β本身。

所谓border,就是next[len(β)],直观含义是除了串本身以外,使得前缀等于后缀的最长的一段前缀。

发现如果border的两倍就能覆盖整个串,那么问题的规模就减半了,只要求出能cover这个border的最短的串即可。这个关系是具有传递性的,只要border够长,就一直可以推下去。而这种关系可以通过一个last数组实现路径压缩。

如果border的两倍不能覆盖整个串,那就要看border的哪一个前缀可以了,那么哪些前缀可以呢?只有哪些border的border才有可能可以。这是为什么呢?因为只有哪些border的border,才是β串的公共前后缀。那么我们通过一个far数组,维护每一个前缀最远能够覆盖到的位置,动态维护这个数组,通过last数组路径压缩加速即可。

要注意的是far数组的更新要一路更新到底,否则无法把信息维护全。

#include<bits/stdc++.h>
using namespace std;

void kmp_pre(char x[],int m,int nxt[])
{
    int i,j;
    j=nxt[0]=-1;
    i=0;
    while(i<m)
    {
        while(-1!=j && x[i]!=x[j])j=nxt[j];
        nxt[++i]=++j;
    }
}

const int maxn=250005;
char s[maxn];
int nxt[maxn];
int last[maxn];
int far[maxn];

int main()
{
    freopen("cover.in","r",stdin);
    freopen("cover.out","w",stdout);
    scanf("%s",s);
    int l=strlen(s);
    kmp_pre(s,l,nxt);
    for (int i=1;i<=l;i++) if (nxt[i]*2>=i) last[i]=last[nxt[i]]; else last[i]=i;
    for (int i=1;i<=l;i++)
    {
        int j=last[i];
        far[j]=i;
        int now=i;
        while (j)
        {
            if (far[j]>=i-j)
            {
                now=j;
                far[now]=i;
            }
            j=last[nxt[j]];
        }
        printf("%d ",now);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/acmsong/p/7634397.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您提供的链接是Codeforces的一个问题,问题编号为104377。Codeforces是一个知名的在线编程竞赛平台,经常举办各种编程比赛和训练。GymCodeforces的一个扩展包,用于组织私人比赛和训练。您提供的链接指向了一个问题的页面,但具体的问题内容和描述无法通过链接获取。如果您有具体的问题或需要了解关于Codeforces Gym的更多信息,请提供更详细的信息。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [http://codeforces.com/gym/100623/attachments E题](https://blog.csdn.net/weixin_30820077/article/details/99723867)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [http://codeforces.com/gym/100623/attachments H题](https://blog.csdn.net/weixin_38166726/article/details/99723856)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [CodeforcesPP:Codeforces扩展包](https://download.csdn.net/download/weixin_42101164/18409501)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值