https://vjudge.net/problem/UVA-1328
题意
求每个前缀的最小循环节,要求至少循环两次且为完整的。
分析
求next数组,i-next[i]即为前缀i的最小循环节,再判断一下限制条件即可。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <algorithm> #include <cmath> #include <ctime> #include <vector> #include <queue> #include <map> #include <stack> #include <set> #include <bitset> using namespace std; typedef long long ll; typedef unsigned long long ull; #define ms(a, b) memset(a, b, sizeof(a)) #define pb push_back #define mp make_pair #define pii pair<int, int> //#define eps 0.0000000001 #define IOS ios::sync_with_stdio(0);cin.tie(0); #define random(a, b) rand()*rand()%(b-a+1)+a #define pi acos(-1) //const ll INF = 0x3f3f3f3f3f3f3f3fll; const int inf = 0x3f3f3f3f; const int maxn = 1e6 + 10; const int maxm = 4e5 +10; const int mod = 20071027; const int sigma_size = 26; char s[maxn]; int f[maxn]; int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); // freopen("input.txt", "w", stdout); #endif int cas=1; int T; int n; while(~scanf("%d",&n)&&n){ scanf("%s",s); f[0]=f[1]=0; for(int i=1;i<n;i++){ int j=f[i]; while(j&&s[i]!=s[j]) j=f[j]; f[i+1]=s[i]==s[j]?j+1:0; } printf("Test case #%d ",cas++); for(int i=2;i<=n;i++){ if(f[i]>0&&i%(i-f[i])==0) printf("%d %d ",i,i/(i-f[i])); } printf(" "); } return 0; }