Codeforces 1080E Sonya and Matrix Beauty hash + manacher

Sonya and Matrix Beauty

处理子矩阵的一般方法, 把多行压缩成一行,然后跑manacher, 压缩的话用hash就好了。

#include<bits/stdc++.h>
using namespace std;

using LL = long long;
using ull = unsigned long long ;

mt19937_64 rng(58);

const int N = 250 + 7;
const ull B = (int)1e6 + 3;

int n, m;
int c[N][N][26];
char s[N][N];
ull Pow[26];
ull V[N];
int p[N];
int odd;

inline ull get(int row, int l, int r, int ch) {
    int cnt = c[row][r][ch] - c[row][l - 1][ch];
    odd += cnt & 1;
    return cnt * Pow[ch];
}

int manacher(ull *s, int n) {
    int ans = 0;
    s[0] = rng(); s[n + 1] = rng();
    int mx = 0, id = 0;
    for(int i = 1; i <= n; i++) {
        if(mx > i) p[i] = min(mx - i, p[2 * id - i]);
        else p[i] = 1;
        while(s[i + p[i]] == s[i - p[i]]) p[i]++;
        if(i + p[i] > mx) mx = i + p[i], id = i;
        ans += p[i];
    }
    mx = 0, id = 0;
    for(int i = 1; i <= n; i++) {
        if(mx > i) p[i] = min(mx - i, p[2 * id - i]);
        else p[i] = 0;
        while(s[i + p[i] + 1] == s[i - p[i]]) p[i]++;
        if(i + p[i] > mx) mx = i + p[i], id = i;
        ans += p[i];
    }
    return ans;
}

int main() {
    for(int i = Pow[0] = 1; i < N; i++) Pow[i] = Pow[i - 1] * B;
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) scanf("%s", s[i] + 1);
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j++) {
            for(int k = 0; k < 26; k++) c[i][j][k] = c[i][j - 1][k];
            c[i][j][s[i][j] - 'a']++;
        }
    }
    LL ans = 0;
    for(int cl = 1; cl <= m; cl++) {
        for(int cr = cl; cr <= m; cr++) {
            int tot = 0;
            for(int r = 1; r <= n; r++) {
                ull hs = 0; odd = 0;
                for(int ch = 0; ch < 26; ch++) {
                    hs += get(r, cl, cr, ch);
                }
                V[r] = hs;
                if((cr - cl & 1) && odd || !(cr - cl & 1) && odd > 1) {
                    ans += manacher(V, tot);
                    tot = 0;
                }
                else {
                    V[++tot] = hs;
                }
            }
            ans += manacher(V, tot);
        }
    }
    printf("%lld\n", ans);
    return 0;
}

 

posted @ 2019-11-06 14:02  NotNight  阅读(204)  评论(0编辑  收藏  举报