zr#955 折纸
分析
我们发现行列独立
只要分别求出答案然后相乘即可
而对于所有行我们可以将其哈希后变为一行
这样就转化为了1*n的问题
代码
#include<bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;
const int H = 233;
string s[100100];
int a[100100],b[100100],pre[100100],sur[100100],p[100100],d[300100];
inline void getman(int a[],int n){
int i,j,k,id=0,mx=1;
for(i=1;i<=n;i++)d[i*2]=a[i],d[i*2+1]=-1;
d[1]=-1,d[0]=-123,d[2*n+2]=-456;
p[0]=1;
for(i=1;i<=2*n+2;i++){
p[i]=i<mx?min(p[2*id-i],mx-i):1;
while(d[i-p[i]]==d[i+p[i]])p[i]++;
if(i+p[i]>mx)id=i,mx=i+p[i];
}
for(i=1;i<=n;i++)p[i]=p[i*2+1]/2;
}
inline int work(int a[],int n){
int i,j,k,ans=0;
memset(pre,0,sizeof(pre));
memset(sur,0,sizeof(sur));
memset(p,0,sizeof(p));
getman(a,n);
k=0;
for(i=1;i<n;i++)if(i-p[i]<=k)k=i,pre[i]=1;
k=n;
for(i=n-1;i>0;i--)if(i+p[i]>=k)k=i,sur[i]=1;
k=1;
for(i=1;i<n;i++){
if(sur[i])ans+=k;
if(pre[i])k++;
}
ans+=k;
return ans;
}
int main(){
int n,m,i,j,k;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)cin>>s[i];
for(i=1;i<=n;i++)
for(j=m;j>0;j--)s[i][j]=s[i][j-1];
for(i=1;i<=n;i++){
for(j=1;j<=m;j++)a[i]=(1ll*a[i]*H%mod+(s[i][j]-'a'))%mod;
}
for(i=1;i<=m;i++){
for(j=1;j<=n;j++)b[i]=(1ll*b[i]*H%mod+(s[j][i]-'a'))%mod;
}
printf("%lld\n",1ll*work(a,n)*work(b,m));
return 0;
}