1 条题解
-
0
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
- 上传者