UVA

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;
}
原文地址:https://www.cnblogs.com/fht-litost/p/9627933.html