POJ--1961/2406 Period/Power Strings(KMP)

记录
18:26 2024-2-22

http://poj.org/problem?id=1961
http://poj.org/problem?id=2406

  • 1961

    利用KMP构造next数组,其实next数组就是方便于找到下一个应该比较的字符,或者说是不动目标字符,移动查找字符,这里面利用next数组就可以很快捷的移动

    这道题是利用next字符,给出证明的结果是
    当 i - next[i] 能整除 i时, S[1 ~ i - next[i]]就是 S[1 ~ i]的最小循环元
    同理 对 i - next[next[i]] 能整除时,S[1 ~ i - next[next[i]]] 就是次小循环元,可以以此找到最大循环元

    next下标从1开始

    点击查看代码
    #include<iostream>
    #include<vector>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    const int INF = 0x3f3f3f3f;
    const int MAXN = 1000005;
    int N;
    int T = 1;
    int nxt[MAXN];
    char str[MAXN];
    
    //下标从1开始
    void calc_next() {
        nxt[1] = 0;
        for (int i = 2, j = 0; i <= N; i++) {
            while (j > 0 && str[i] != str[j+1]) j = nxt[j];
            if (str[i] == str[j+1]) j++;
            nxt[i] = j;
        }
    }
    
    int main() {
        while (cin >> N && N != 0) {
            scanf("%s", str + 1);
            calc_next();
            printf("Test case #%d\n", T);
            T++;
            for(int i = 2; i <= N; i++) {
                if(i % (i - nxt[i]) == 0 && i / (i - nxt[i]) > 1) {
                    printf("%d %d\n", i, i / (i - nxt[i]) );
                }
            }
            printf("\n");
        }
        
    }
    
    

    next下标从0开始

    点击查看代码
    #include<iostream>
    #include<vector>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    const int INF = 0x3f3f3f3f;
    const int MAXN = 1000005;
    int N;
    int T = 1;
    int nxt[MAXN];
    char str[MAXN];
    
    //下标从0开始
    void calc_next() {
        nxt[0] = -1;
        for (int i = 1, j = -1; i < N; i++) {
            while (j >= 0 && str[i] != str[j+1]) j = nxt[j];
            if (str[i] == str[j+1]) j++;
            nxt[i] = j;
        }
    }
    
    int main() {
        while (cin >> N && N != 0) {
            scanf("%s", str);
            calc_next();
            printf("Test case #%d\n", T);
            T++;
            //如果从零开始 要变为i + 1
            for(int i = 1; i < N; i++) {
                if((i + 1) % (i - nxt[i]) == 0 && (i + 1) / (i - nxt[i]) > 1) {
                    printf("%d %d\n", (i + 1), (i + 1) / (i - nxt[i]) );
                }
            }
            printf("\n");
        }
        
    }
    
    
  • 2406

    点击查看代码
    #include<iostream>
    #include<vector>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    const int INF = 0x3f3f3f3f;
    const int MAXN = 1000005;
    int N;
    int nxt[MAXN];
    char str[MAXN];
    
    //下标从0开始
    void calc_next() {
        nxt[0] = -1;
        for (int i = 1, j = -1; i < N; i++) {
            while (j >= 0 && str[i] != str[j+1]) j = nxt[j];
            if (str[i] == str[j+1]) j++;
            nxt[i] = j;
        }
    }
    
    int main() {
        while (scanf("%s", str) && str[0] != '.') {
            N = strlen(str);
            calc_next();
            int result = 1;
            //如果从零开始 要变为i + 1
            // for(int i = 1; i < N; i++) {
            //     if((i + 1) % (i - nxt[i]) == 0 && (i + 1) / (i - nxt[i]) > 1) {
            //         result = max(result, (i + 1) / (i - nxt[i]));
            //     }
            // }
    
            // 这里计算是对整个字符串
            if(N % (N - 1 - nxt[N - 1]) == 0 && N / (N - 1 - nxt[N - 1]) > 1) {
                result = max(result, N / (N - 1 - nxt[N - 1]));
            }
            printf("%d\n", result);
        }
        
    }
    
    
posted @ 2024-02-22 21:38  57one  阅读(14)  评论(0)    收藏  举报