• Codeforces 432 D. Prefixes and Suffixes



    随着扩展KMP做一个简单的努力.....

    D. Prefixes and Suffixes
    time limit per test
    1 second
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    You have a string s = s1s2...s|s|, where |s| is the length of string s, and si its i-th character.

    Let's introduce several definitions:

    • A substring s[i..j] (1 ≤ i ≤ j ≤ |s|) of string s is string sisi + 1...sj.
    • The prefix of string s of length l (1 ≤ l ≤ |s|) is string s[1..l].
    • The suffix of string s of length l (1 ≤ l ≤ |s|) is string s[|s| - l + 1..|s|].

    Your task is, for any prefix of string s which matches a suffix of string s, print the number of times it occurs in string s as a substring.

    Input

    The single line contains a sequence of characters s1s2...s|s| (1 ≤ |s| ≤ 105) — string s. The string only consists of uppercase English letters.

    Output

    In the first line, print integer k (0 ≤ k ≤ |s|) — the number of prefixes that match a suffix of string s. Next print k lines, in each line print two integers li ci. Numbers li ci mean that the prefix of the length li matches the suffix of length li and occurs in string s as a substringci times. Print pairs li ci in the order of increasing li.

    Sample test(s)
    input
    ABACABA
    
    output
    3
    1 4
    3 2
    7 1
    
    input
    AAA
    
    output
    3
    1 3
    2 2
    3 1


    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn=100100;
    
    char T[maxn],P[maxn];
    int next[maxn],ex[maxn];
    
    void pre_exkmp(char P[])
    {
        int m=strlen(P);
        next[0]=m;
        int j=0,k=1;
        while(j+1<m&&P[j]==P[j+1]) j++;
        next[1]=j;
        for(int i=2;i<m;i++)
        {
            int p=next[k]+k-1;
            int L=next[i-k];
            if(i+L<p+1) next[i]=L;
            else
            {
                j=max(0,p-i+1);
                while(i+j<m&&P[i+j]==P[j]) j++;
                next[i]=j; k=i;
            }
        }
    }
    
    void exkmp(char P[],char T[])
    {
        int m=strlen(P),n=strlen(T);
        pre_exkmp(P);
        int j=0,k=0;
        while(j<n&&j<m&&P[j]==T[j]) j++;
        ex[0]=j;
        for(int i=1;i<n;i++)
        {
            int p=ex[k]+k-1;
            int L=next[i-k];
            if(i+L<p+1) ex[i]=L;
            else
            {
                j=max(0,p-i+1);
                while(i+j<n&&j<m&&T[i+j]==P[j]) j++;
                ex[i]=j; k=i;
            }
        }
    }
    
    int pos[maxn],sum[maxn],mx=-1;
    
    struct ANS
    {
        int a,b;
    }ans[maxn];
    int na=0;
    
    bool cmp(ANS x,ANS y)
    {
        if(x.a!=y.a)return x.a<y.a;
        return x.b<y.b;
    }
    
    int lisan[maxn],nl;
    
    int main()
    {
        cin>>P;
        pre_exkmp(P);
        int n=strlen(P);
        for(int i=0;i<n;i++)
        {
            pos[next[i]]++;
            lisan[nl++]=next[i];
            mx=max(mx,next[i]);
        }
        sort(lisan,lisan+nl);
        int t=unique(lisan,lisan+nl)-lisan;
        for(int i=t-1;i>=0;i--)
        {
            sum[lisan[i]]=sum[lisan[i+1]]+pos[lisan[i]];
        }
        for(int i=0;i<n;i++)
        {
            if(next[i]==n-i)
            {
                ans[na++]=(ANS){next[i],sum[next[i]]};
            }
        }
        sort(ans,ans+na,cmp);
        printf("%d
    ",na);
        for(int i=0;i<na;i++)
        {
            printf("%d %d
    ",ans[i].a,ans[i].b);
        }
        return 0;
    }
    




    版权声明:来自: 代码代码猿猿AC路 http://blog.csdn.net/ck_boss

  • 相关阅读:
    JavaScript实现HTML导航栏下拉菜单[悬浮显示]
    Paper Pal:一个中英文论文及其代码大数据搜索平台
    小程序定位地图模块全系列开发教学(超详细)
    简单的个人介绍网页主页面【附代码】
    前端分页功能(通用)
    打造完美写作系统:Gitbook+Github Pages+Github Actions
    移动端布局
    三剑客var,let,const
    包含多个段的程序01 零基础入门学习汇编语言29
    更灵活的定位内存地址的方法01 零基础入门学习汇编语言32
  • 原文地址:https://www.cnblogs.com/yxwkf/p/4848739.html
Copyright © 2020-2023  润新知