HDOJ4029 不同子矩阵的个数

来源:互联网 发布:主升浪选股软件 编辑:程序博客网 时间:2024/05/16 06:47

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.
 

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.
 

Output
For each test case, output a single integer denoting the number of distinct sub-matrices.
 

Sample Input
22 2ABBA3 3ABABAAAAA
 

Sample Output
Case #1: 7Case #2: 22
 

Source
The 36th ACM/ICPC Asia Regional Shanghai Site —— Online Contest
 

Recommend
lcy   |   We have carefully selected several similar problems for you:  4028 4030 4026 4022 4023 
后缀数组该停停了,这个题等学了hash在再做,先收藏一下得了
ac代码 
#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <map>#define maxn 100005using 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;}


0 0