【二维循环节 字符串hash】 奶牛矩阵

传送门

题意

给定一个\(r\)\(c\)列的矩阵,求出一个最小覆盖矩阵,即循环节矩阵
即这个矩阵无限扩张后的矩阵能够包含原来的完整矩阵,输出当前矩阵的面积

数据范围

\(\begin{array}{l}1 \leq R \leq 10000 \\ 1 \leq C \leq 75\end{array}\)

题解

\(hash\)\(kmp\)分别求所有行最小循环节长度,所有列的最小循环节长度,当前矩阵可能是由部分循环节构成
所以可能是当前不完美的循环节,二者相乘即最小覆盖矩阵。

Code

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define ll long long
#define ull unsigned long long 

const int N=1e4+10;
const ull P=13331;
int ne[N];
int r,c;
char s[N][100];
ull h[N*100],p[N];
int get(int d)
{
    memset(ne,0,sizeof ne);
    int j=0;
    rep(i,2,d+1)
    {
        while(j && h[i]!=h[j+1]) j=ne[j];
        if(h[i]==h[j+1]) j++;
        ne[i]=j;
    }
    return d-ne[d];
}
void solve()
{  
    cin>>r>>c;
    rep(i,1,r+1) cin>>s[i]+1;
    rep(i,1,r+1) rep(j,1,c+1)
        h[i]=h[i]*P + s[i][j];
    int ar=get(r);
    memset(h,0,sizeof h);
    rep(i,1,c+1) rep(j,1,r+1)
        h[i]=h[i]*P+s[j][i];
    int ac=get(c);

    cout<<ac*ar<<endl;

}
int main()
{
    solve();
}

posted @ 2020-09-28 20:58  Hyx'  阅读(145)  评论(0)    收藏  举报