得られる\(R \倍C \)文字マトリックスの、元の文字マトリクスサブマトリックスに拡張した後に連続自己複製のための被覆マトリクスを規定最小カバレッジ呼び掛けマトリックス、\(1≤R≤10000を、 1≤C≤75 \) 。
ソリューション
研究からはシンプルで、2次元の始まりを勉強しない、彼の党のために、我々は結論を見つけ、それを左に整列するためにバインドされ、そのカバレッジ・マトリックスは、自己理解の図を描き、ですので、2次元に拡張することが可能でなければならず、左上隅の位置を合わせます。
また、回答の観点から、元の行列を覆う、無制限の拡張のためのサブ行列で独立性質のランクは、我々が行のRライン文字を押すことができ、それは、サブ行列の列になり見出さ問題、同じプロセスは、カラム上で行うことができ、我々は答えを見つけるような長さの二つのサブ行列の積(漠然と感じには右である、それは理にかなって、私が言うことができません)。
どのように複数の行が私たちがキャリアを座ってするアルゴリズムを見つける必要がある「部分文字列をカバーする」の文字列を検索する方法を、次の文字列が問題となるので、それをハッシュ、ラインに押し込まれます、我々はハッシュ文字列のことを学びました、KMP、トライ、最小の表現は、いくつかのモデル(例えば、最長のサブストリングパリンドローム)がある、KMPを検討し、次に最小の性質は、「ストリングを覆う」ことを見出し文字列の長さ-next [文字列の長さの長さであります]、自己描画がどのようなことができます理解しています。
私たちにできる最後の時間複雑\(O(RC)\) 。
参照コード:
#include <iostream>
#include <cstdio>
#include <cstring>
#define il inline
#define ri register
#define ll long long
#define ull unsigned ll
#define jzm 19260817
using namespace std;
char s[15000][100];
int Next[15000];
ull qz[15000],base[15000];
il int kmp(int);
il void get(char&);
int main(){
int r,c,ans(1);base[0]=1;
for(int i(1);i<=10000;++i)
base[i]=base[i-1]*jzm;
scanf("%d%d",&r,&c);
for(int i(1),j;i<=r;++i)
for(j=1;j<=c;++j)
get(s[i][j]);
for(int i(1),j;i<=r;++i)
for(j=1;j<=c;++j)
qz[i]=qz[i]*jzm+s[i][j];
ans=kmp(r),memset(qz,0,sizeof(qz));
for(int i(1),j;i<=c;++i)
for(j=1;j<=r;++j)
qz[i]=qz[i]*jzm+s[j][i];
ans*=kmp(c),printf("%d",ans);
return 0;
}
il int kmp(int n){
for(int i(2),j(0);i<=n;++i){
while(j&&qz[i]!=qz[j+1])j=Next[j];
if(qz[i]==qz[j+1])++j;Next[i]=j;
}return n-Next[n];
}
il void get(char &c){
while(c=getchar(),c==' '||c=='\n'||c=='\r');
}