AtCoder Beginner Contest 141. E - Who Says a Pun? (后缀数组)

https://atcoder.jp/contests/abc141/tasks/abc141_e
AtCoder Beginner Contest 141. E - Who Says a Pun? (后缀数组)_第1张图片
AtCoder Beginner Contest 141. E - Who Says a Pun? (后缀数组)_第2张图片

AC Code(Suffix array)[A foolish way to solve the problem]

//#include
#include
#include
#include
#include
#include
#include
#include
#include

using namespace std;
typedef long long ll;
const int MAXN = 20005;

char s[MAXN];
int n, k;
int t1[MAXN], t2[MAXN], c[MAXN];
int _rank[MAXN], height[MAXN], sa[MAXN];

bool cmp(int *r, int a, int b, int l) { return r[a] == r[b] && r[a + l] == r[b + l]; }

void da(char str[], int sa[], int rank[], int height[], int n, int m) {
    n++;
    int i, j, p, *x = t1, *y = t2;
    for (i = 0; i < m; i++)c[i] = 0;
    for (i = 0; i < n; i++)c[x[i] = str[i]]++;
    for (i = 1; i < m; i++)c[i] += c[i - 1];
    for (i = n - 1; i >= 0; i--)sa[--c[x[i]]] = i;
    for (j = 1; j <= n; j <<= 1) {
        p = 0;
        for (i = n - j; i < n; i++)
            y[p++] = i;
        for (i = 0; i < n; i++)
            if (sa[i] >= j)
                y[p++] = sa[i] - j;
        for (i = 0; i < m; i++)c[i] = 0;
        for (i = 0; i < n; i++)c[x[y[i]]]++;
        for (i = 1; i < m; i++)c[i] += c[i - 1];
        for (i = n - 1; i >= 0; i--)
            sa[--c[x[y[i]]]] = y[i];
        swap(x, y);
        p = 1;
        x[sa[0]] = 0;
        for (i = 1; i < n; i++) x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++;
        if (p >= n)break;
        m = p;
    }
    int k = 0;
    n--;
    for (i = 0; i <= n; i++)rank[sa[i]] = i;
    for (i = 0; i < n; i++) {
        if (k)k--;
        j = sa[rank[i] - 1];
        while (str[i + k] == str[j + k])k++;
        height[rank[i]] = k;
    }
}

int getRepeatTimes(int l, int len) {
    int res = l;
    while (height[res] >= len && res <= n) res++;
    return res - l + 1;
}

/**
 * ÅжÏÊÇ·ñÓ㈶ÈΪlenµÄÖØžŽkŽÎŒ°ÒÔÉϵĵÄ×ÓŽ®
 * @param len
 * @return
 */
bool repeatsMoreThanK(int len) {
    int l = 2;
    while (l <= n) {
        if (height[l] >= len) {
            int times = getRepeatTimes(l, len);
            if (times >= k)
                return true;
            l += times - 1;
        } else ++l;
    }
    return false;
}

bool repeatsMoreThanK(int n, int k) {
    int maxi = -1, mini = 0x3f3f3f3f;
    for (int i = 1; i <= n; ++i) {
        if (height[i] < k)
            maxi = sa[i], mini = sa[i];
        else {
            maxi = max(maxi, max(sa[i], sa[i - 1]));
            mini = min(mini, min(sa[i], sa[i - 1]));
            if (maxi - mini >= k) return true;
        }
    }
    return false;
}

int main() {
    k = 2;
    scanf("%d", &n);
    scanf("%s", s);
    s[n] = 0;
    da(s, sa, _rank, height, n, 128);
    int ans = 0, l = 1, r = n;
    while (l <= r) {
        int mid = (l + r) >> 1;
        if (repeatsMoreThanK(n, mid))
            ans = mid, l = mid + 1;
        else
            r = mid - 1;
    }
    printf("%d\n", ans);
    return 0;
}

AC Code(String hash) [Another stupid way to solve the problem]

//#include
#include
#include 
#include 

using namespace std;
typedef long long ll;
const int MAXN = 20005;

char s[MAXN];
int n, k;

typedef long long ll;
const ll mod = static_cast<const ll>(1e9 + 7);
const int maxn = static_cast<const int>(1e6 + 5);
#define base 131

ll po[maxn];
ll po1[maxn];

// 0 based, l, arr inclusive.
ll getHash(const ll _hash[], int l, int r) {
    return (_hash[r] - _hash[l - 1] * po[r - l + 1] % mod + mod) % mod;
}

ll getHash2(const ll _hash[], int l, int r) {
    return (_hash[r] - _hash[l - 1] * po1[r - l + 1] % mod + mod) % mod;
}

ll strHash[maxn];
ll strHash2[maxn];

void init() {
    po[0] = 1;
    for (int i = 1; i < maxn; ++i)
        po[i] = (po[i - 1] * base) % mod;
    po1[0] = 1;
    for (int i = 1; i < maxn; ++i)
        po1[i] = (po1[i - 1] * 97) % mod;
}

void initHash(const char *str, ll *_hash, int ba) {
    _hash[0] = str[0] - '0';
    for (int i = 1; str[i]; i++)
        _hash[i] = ((_hash[i - 1] * ba) % mod + str[i] - '0') % mod;
}


bool repeatsMoreThanK(int len) {
    int cnt = 1;
    for (int i = 0; i + len - 1 < n; ++i) {
        ll baseHash = getHash(strHash, i, i + len - 1);
        ll baseHash2 = getHash2(strHash2, i, i + len - 1);
        cnt = 1;
        for (int j = i + len; j + len - 1 < n; ++j) {
            ll currHash = getHash(strHash, j, j + len - 1);
            ll currHash2 = getHash2(strHash2, j, j + len - 1);
            if (currHash == baseHash && baseHash2 == currHash2) {
                ++cnt;
                if (cnt >= k)
                    return true;
            }
        }
    }
    return false;
}


int main() {
    k = 2;
    scanf("%d", &n);
    scanf("%s", s);
    init();
    initHash(s, strHash, 131);
    initHash(s, strHash2, 97);
//    da(s, sa, _rank, height, n, 128);
    int ans = 0, l = 1, r = n;
    while (l <= r) {
        int mid = (l + r) >> 1;
        if (repeatsMoreThanK(mid))
            ans = mid, l = mid + 1;
        else
            r = mid - 1;
    }
    printf("%d\n", ans);
    return 0;
}


AC Code(666)

#include 

using namespace std;

int n;
char S[5005];
int A[5005];

int solve(char S[], int n) {
    int l = -1, r = -1;
    for (int i = 1; i < n; ++i) {
        if (i <= r) A[i] = min(r - i, A[i - l]);
        else A[i] = -1;
        while (i + A[i] + 1 < n && S[i + A[i] + 1] == S[A[i] + 1]) ++A[i];
        if (r < i + A[i]) r = i + A[i], l = i;
    }
    int ret = 0;
    for (int i = 1; i < n; ++i) {
        ret = max(ret, min(A[i] + 1, i));
    }
    return ret;
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cin >> n >> S + 1;
    int ans = 0;
    for (int i = 1; i <= n; ++i) ans = max(ans, solve(S + i, n - i + 1));
    cout << ans;
    return 0;
}

你可能感兴趣的:(ACM,字符串)