E - Power Strings POJ - 2406 (後綴數組||kmp)

這個題目是後綴數組專題裏面的一道題目。結果就是照着後綴數組的思路寫的果然超時了。結果上網一搜才發現kmp也能做,真是太死板了,做題。
思路:對於一個串如果它是某個串的重複得到的,那麼當前串的某個後綴串suff(i)與這串的公共前綴剛好就是那個後綴串suff(i),並且串長能整除i那麼這個串就是長度爲i的重複串。
AC代碼:

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
#define Max_N (1000000 + 100)
int next1[Max_N];
void kmp_pre(char x[], int m, int next1[])
{
    int i, j;
    j = next1[0] = -1;
    i = 0;
    while (i < m)
    {
        while(-1 != j && x[i] != x[j]) j = next1[j];
        next1[++i] = ++j;
    }
}
char buf[Max_N];
int main()
{
    while (true) {
        scanf("%s", buf);
        if (buf[0] == '.') return 0;
        kmp_pre(buf, strlen(buf), next1);
        int len = strlen(buf);
        int ans = 0;
        if (len % (len - next1[len]) == 0) ans = len / (len - next1[len]);
        else ans = 1;
        cout << ans << endl;
    }
}

後綴超時代碼:

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
#define Max_N (1000000 + 100)
#define INF 0x3f3f3f3f
int n;
int k;
int a[Max_N];
int rank1[Max_N];
int tmp[Max_N];
bool compare_sa(int i, int j)
{
    if(rank1[i] != rank1[j]) return rank1[i] < rank1[j];
    else {
        int ri = i + k <= n ? rank1[i + k] : -1;
        int rj = j + k <= n ? rank1[j + k] : -1;
        return ri < rj;
    }
}

void construct_sa(int buf[], int s, int sa[])
{
    int len = s;
    for (int i = 0; i <= len; i++) {
        sa[i] = i;
        rank1[i] = i < len ? buf[i] : -1;
    }

    for ( k = 1; k <= len; k *= 2) {
        sort(sa, sa + len +1, compare_sa);
        tmp[sa[0]] = 0;
        for (int i = 1; i <= len; i++) {
            tmp[sa[i]] = tmp[sa[i-1]] + (compare_sa(sa[i-1], sa[i]) ? 1 : 0);
        }
        for (int i = 0; i <= len; i++) {
            rank1[i] = tmp[i];
        }
    }
}

void construct_lcp(int buf[], int len, int *sa, int *lcp)
{
    int h = 0;
    lcp[0] = 0;
    for (int i = 0; i < len; i++) {
        int j = sa[rank1[i] - 1];
        if (h > 0) h--;
        for (; j + h < len && i + h < len; h++) {
            if (buf[j+h] != buf[i+h]) break;
        }
        lcp[rank1[i] - 1] = h;
    }
}
int sa[Max_N];
int lcp[Max_N];
char buf1[Max_N];
int min1[Max_N];
int main()
{ 
    while (true) {
        scanf("%s", buf1);
        if(buf1[0] == '.') break;
        n = strlen(buf1);
        for (int i = 0; i < n; i++) {
            a[i] = int(buf1[i]);
        }
        construct_sa(a, n, sa);
        construct_lcp(a, n, sa, lcp);
        min1[rank1[0]] = INF;
        for (int i = rank1[0]; i < n-1; i++) {
            min1[i+1] = min(lcp[i], min1[i]);
        }

        for (int i = rank1[0]-1; i  >= 0; i--) {
            min1[i] = min(lcp[i], min1[i+1]);
        }
        int ans = 1;
        for (int i = 1; i < n; i++) {
            //cout << min1[rank1[i]] << endl;
            if (min1[rank1[i]] == n - i && n % i == 0) {
                ans = max(ans, n/i);
            }
        }
        cout << ans << endl;
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章