當每個Word是字母時,相當于統計subgrid出現了多少個dictionary中的字母。可以先預處理得到字首和presum[i,j],表示subgrid (左上角[0,0]右下角[i,j] inclusive)中出現了多少dictionary中的字母,presum可以通過dp+容斥原理得出:presum[i,j]=presum[i-1,j]+presum[i,j-1]-presum[i-1,j-1]。如此,枚舉subgrid左上角(a,b)和右下角(c,d),subgrid中的word出現次數presum[c,d]-presum[a,d]-presum[c,b]+presum[a,b]。每出現1次,對最後的結果貢獻是4。
輸入是字元串真是坑爹。開始一直Incorrect是因為輸入一個Word W[i]之後沒有cin.ignore(),于是W[i+1]輸入的就是空字元,W[i+2]才是W[i+1]對應的值。
#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<stdlib.h>
#include<vector>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<queue>
#include<ctype.h>
#include<map>
#include<time.h>
#include<set>
#include<bitset>
#include<sstream>
using namespace std;
//2018 round D Problem C. Funniest Word Search small
const int maxn=110;
int T;
int R;
int C;
int W;
int mp[maxn][maxn];
//char mp[maxn][maxn];
int matrix[maxn][maxn];
int dict[30];
int ans1; //numerator
int presum[maxn][maxn];
int ans2; //denominator
int quickgcd(int a,int b)
{
if(a==0) return b;
if(b==0) return a;
if(!(a&1)&&!(b&1)) return quickgcd(a>>1,b>>1)<<1;
else if(!(b&1)) return quickgcd(a,b>>1);
else if(!(a&1)) return quickgcd(a>>1,b);
else return quickgcd(abs(a-b),min(a,b));
}
//set<int>words;
//set<char>words;
int main()
{
cin>>T;
for(int ca=1;ca<=T;ca++)
{
// cout<<ca<<endl;
// if(ca>3) return 0;
memset(mp,0,sizeof(mp));
memset(dict,0,sizeof(dict));
memset(matrix,0,sizeof(matrix));
memset(presum,0,sizeof(presum));
// words.clear();
ans1=0;
ans2=0;
scanf("%d %d %d",&R,&C,&W);
for(int i=1;i<=R;i++)
{
char tmp[maxn];
scanf("%s",tmp);
// cout<<tmp<<endl;
// cout<<C<<endl;
// cout<<strlen(tmp)<<endl;
if(strlen(tmp)!=C)
{
cout<<"error"<<endl;
}
for(int j=1;j<=C;j++)
{
// cout<<tmp[j]<<endl;
mp[i][j]=tmp[j-1]-'A';
// mp[i][j]=tmp[j-1];
}
// cout<<mp[i]<<endl;
}
// for(int j=1;j<=R;j++)
// {
// for(int k=1;k<=C;k++)
// {
// cout<<mp[j][k]<<" ";
// }
// cout<<endl;
// }
// cout<<"here"<<endl;
cin.ignore();//otherwise, can not input the following characters.
for(int i=0;i<W;i++)
{
char tmp;
scanf("%c",&tmp);
cin.ignore();//without it, dict[i+1] saves the empty character instead of the next character
// cout<<tmp<<" "<<(tmp-'A')<<endl;
dict[i]=tmp-'A';
// words.insert(tmp-'A');
// words.insert(tmp);
}
// for(int i=0;i<W;i++)
// {
// cout<<dict[i]<<" ";
// }
// cout<<endl;
for(int i=0;i<W;i++)
{
// cout<<dict[i]<<endl;
for(int j=1;j<=R;j++)
{
for(int k=1;k<=C;k++)
{
if(mp[j][k]==dict[i])
{
matrix[j][k]+=4;//each word appears only once
}
}
}
}
// for(int j=0;j<=R;j++)
// {
// for(int k=0;k<=C;k++)
// {
// cout<<matrix[j][k]<<" ";
// }
// cout<<endl;
// }
for(int i=1;i<=R;i++)
{
for(int j=1;j<=C;j++)
{
presum[i][j]=presum[i-1][j]+presum[i][j-1]-presum[i-1][j-1]+matrix[i][j];
// if(words.find(mp[i][j])!=words.end())
// {
// presum[i][j]+=4;
// }
}
}
// for(int i=0;i<=R;i++)
// {
// cout<<"row "<<i<<" ";
// for(int j=0;j<=C;j++)
// {
// cout<<presum[i][j]<<" ";
// }
// cout<<endl;
// }
for(int i=0;i<=R;i++)
{
for(int j=0;j<=C;j++)
{
for(int l=i+1;l<=R;l++)
{
for(int m=j+1;m<=C;m++)
{
// cout<<i<<" "<<j<<" "<<l<<" "<<m<<endl;
int tmp=presum[l][m]+presum[i][j]-presum[i][m]-presum[l][j];
if(ans2==0)
{
ans1=tmp;
ans2=l-i+m-j;
int gcd=quickgcd(ans1,ans2);
ans1/=gcd;
ans2/=gcd;
}
else
{
int size=l-i+m-j;
if(tmp*ans2>size*ans1)
{
ans1=tmp;
ans2=size;
int gcd=quickgcd(ans1,ans2);
ans1/=gcd;
ans2/=gcd;
}
}
}
}
}
}
int cnt=0;
for(int i=0;i<=R;i++)
{
for(int j=0;j<=C;j++)
{
for(int l=i+1;l<=R;l++)
{
for(int m=j+1;m<=C;m++)
{
int tmp=presum[l][m]+presum[i][j]-presum[i][m]-presum[l][j];
int size=l-i+m-j;
if(tmp*ans2==size*ans1)
{
// cout<<i<<" "<<j<<" "<<l<<" "<<m<<endl;
cnt++;
}
}
}
}
}
printf("Case #%d: %d/%d %d\n",ca,ans1,ans2,cnt);
}
return 0;
}