1 条题解

  • 0
    @ 2025-5-4 14:38:42

    KMP 算法预处理:利用 KMP 算法中的 next 数组(部分匹配表)来分析字符串的前缀结构。next [i] 表示字符串前 i 个字符的最长相等前缀和后缀的长度。重复子串检测原理:对于字符串的前 i 个字符,若存在长度为 len 的子串重复 k 次构成该前缀说明存在有效重复子串。算法步骤:构建字符串 c 的 next 数组。遍历每个位置 i(1 ≤ i ≤ m),检查:i % (i - next[i]) == 0:确保 i 是最小重复子串长度的整数倍。i / (i - next[i]) != 1:确保重复次数至少为 2 次。

    
    #include<iostream>
    #include<cstring>
    #include<queue>
    #include<map>
    #include<stack>
    #include<cmath>
    #include<cstdio>
    #include<iomanip>
    #include<sstream>
    #include<algorithm>
     
    using namespace std;
    #define read(x) scanf("%d",&x)
    #define Read(x,y) scanf("%d%d",&x,&y)
    #define sRead(x,y,z)  scanf("%d%d%d",&x,&y,&z)
    #define gc(x)  scanf(" %c",&x);
    #define mmt(x,y)  memset(x,y,sizeof x)
    #define write(x) printf("%d\n",x)
    #define INF 0x3f3f3f3f
    #define ll long long
    #define mod  998244353
    #define pdd pair<double,double>
    const int N = 1000;
    const int M=  1e6;
    char c[M+5],s[M+5];
    int m;
    int Next[M+5];
    void kmp_pre()
    {
        int i = 0;
        int j = Next[0] = -1;
        while(i < m){
            while(j != -1 && c[i]!=c[j]) j = Next[j];
            Next[++i] = ++j;
        }
    }
    int main()
    {
        int  k = 1;
        while(~scanf("%d",&m)&&m){
            mmt(Next,0);
            scanf("%s",c);
            printf("Test case #%d\n",k++);
            kmp_pre();
            for(int i = 1;i <= m;++i){
                if(i%(i - Next[i]) == 0&&i / (i - Next[i])!=1){
                    cout<<i<<" "<<i / (i - Next[i])<<endl;
                }
            }
            puts("");
        }
    }
     
    
    
    • 1

    信息

    ID
    962
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者