Distinct Sub-matrix
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 165768/165768 K (Java/Others)Total Submission(s): 830 Accepted Submission(s): 249
Problem Description
In this problem, let us consider an N*M matrix of capital letters. By selecting consecutive columns and rows, we can define the sub-matrix as the elements on chosen columns and rows.
Two sub-matrices should be regarded the same if and only if they have the same dimensions and characters (which, of course, are capital letters) on corresponding position. It is your task to find the number of distinct sub-matrices of a given letter matrix.
Two sub-matrices should be regarded the same if and only if they have the same dimensions and characters (which, of course, are capital letters) on corresponding position. It is your task to find the number of distinct sub-matrices of a given letter matrix.
Input
The input contains a lot of test cases. The first line of input contains exactly one integer, indicating the number of test cases.
For each of the test case, the first line contains two integers N and M, denoting the number of rows and columns of the given matrix. (1 <= N, M <= 128)
The next N lines contain only capital letters, indicating the given matrix.
For each of the test case, the first line contains two integers N and M, denoting the number of rows and columns of the given matrix. (1 <= N, M <= 128)
The next N lines contain only capital letters, indicating the given matrix.
Output
For each test case, output a single integer denoting the number of distinct sub-matrices.
Sample Input
2 2 2 AB BA 3 3 ABA BAA AAA
Sample Output
Case #1: 7 Case #2: 22
Source
Recommend
后缀数组该停停了,这个题等学了hash在再做,先收藏一下得了
ac代码
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <map>
#define maxn 100005
using namespace std;
typedef unsigned long long ull;
const int base = 103;
int str[maxn];
int sa[maxn],t1[maxn],t2[maxn],c[maxn],n;
void suffix(int m)
{
int *x=t1,*y=t2;
for(int i=0; i<m; i++)c[i]=0;
for(int i=0; i<n; i++)c[x[i]=str[i]]++;
for(int i=1; i<m; i++)c[i]+=c[i-1];
for(int i=n-1; i>=0; i--)sa[--c[x[i]]]=i;
for(int k=1; k<=n; k<<=1)
{
int p=0;
for(int i=n-k; i<n; i++)y[p++]=i;
for(int i=0; i<n; i++)if(sa[i]>=k)y[p++]=sa[i]-k;
for(int i=0; i<m; i++)c[i]=0;
for(int i=0; i<n; i++)c[x[y[i]]]++;
for(int i=0; i<m; i++)c[i]+=c[i-1];
for(int i=n-1; i>=0; i--)sa[--c[x[y[i]]]]=y[i];
swap(x,y);
p=1;
x[sa[0]]=0;
for(int i=1; i<n; i++)
x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
if(p>=n)break;
m=p;
}
}
int rank[maxn],height[maxn];
void getheight()
{
int k=0;
for(int i=0; i<n; i++)rank[sa[i]]=i;
for(int i=0; i<n; i++)
{
if(k)k--;
if(!rank[i])continue;
int j=sa[rank[i]-1];
while(str[i+k]==str[j+k])k++;
height[rank[i]]=k;
}
}
char ch[200][200];
ull hash[200][200];
map <ull,int>cq;
int main()
{
int T;
scanf("%d",&T);
for(int cas=1;cas<=T;cas++)
{
int N,M;
scanf("%d%d",&N,&M);
for(int i=0;i<N;i++)
scanf("%s",ch[i]);
ull ans=0;
memset(hash,0,sizeof hash);
for(int w=1;w<=M;w++)
{
int tot=0;
cq.clear();
for(int i=0;i<N;i++)
for(int j=0;j+w-1<M;j++){
hash[i][j]=hash[i][j]*base+ch[i][j+w-1]-'A';
if(!cq[hash[i][j]])cq[hash[i][j]]=++tot;
}
int cnt=0;
for(int j=0;j+w-1<M;j++){
for(int i=0;i<N;i++)
{
str[cnt++]=cq[hash[i][j]];
}
str[cnt++]=++tot;
}
str[cnt-1]=0;
n=cnt;
suffix(tot);
getheight();
ull tmp = (N*(N+1)/2)*(M-w+1);
for(int i=1;i<cnt;i++){
tmp-=height[i];
}
ans+=tmp;
}
printf("Case #%d: %I64d\n",cas,ans);
}
return 0;
}