codeforces1080E. Sonya and Matrix Beauty (马拉车)

                                                E. Sonya and Matrix Beauty

time limit per test

1.5 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Sonya had a birthday recently. She was presented with the matrix of size n×mn×m and consist of lowercase Latin letters. We assume that the rows are numbered by integers from 11 to nn from bottom to top, and the columns are numbered from 11 to mm from left to right.

Let's call a submatrix (i1,j1,i2,j2)(i1,j1,i2,j2) (1≤i1≤i2≤n;1≤j1≤j2≤m)(1≤i1≤i2≤n;1≤j1≤j2≤m) elements aijaij of this matrix, such that i1≤i≤i2i1≤i≤i2 and j1≤j≤j2j1≤j≤j2. Sonya states that a submatrix is beautiful if we can independently reorder the characters in each row (not in column) so that all rows and columns of this submatrix form palidroms.

Let's recall that a string is called palindrome if it reads the same from left to right and from right to left. For example, strings abacaba,bcaacb,aabacaba,bcaacb,a are palindromes while strings abca,acbba,ababca,acbba,ab are not.

Help Sonya to find the number of beautiful submatrixes. Submatrixes are different if there is an element that belongs to only one submatrix.

Input

The first line contains two integers nn and mm (1≤n,m≤250)(1≤n,m≤250) — the matrix dimensions.

Each of the next nn lines contains mm lowercase Latin letters.

Output

Print one integer — the number of beautiful submatrixes.

Examples

input

Copy

1 3
aba

output

Copy

4

input

Copy

2 3
aca
aac

output

Copy

11

input

Copy

3 5
accac
aaaba
cccaa

output

Copy

43

Note

In the first example, the following submatrixes are beautiful: ((1,1),(1,1));((1,2),(1,2));((1,1),(1,1));((1,2),(1,2)); ((1,3),(1,3));((1,1),(1,3))((1,3),(1,3));((1,1),(1,3)).

In the second example, all submatrixes that consist of one element and the following are beautiful: ((1,1),(2,1));((1,1),(2,1)); ((1,1),(1,3));((2,1),(2,3));((1,1),(2,3));((2,1),(2,2))((1,1),(1,3));((2,1),(2,3));((1,1),(2,3));((2,1),(2,2)).

Some of the beautiful submatrixes are: ((1,1),(1,5));((1,2),(3,4));((1,1),(1,5));((1,2),(3,4)); ((1,1),(3,5))((1,1),(3,5)).

The submatrix ((1,1),(3,5))((1,1),(3,5)) is beautiful since it can be reordered as:

accca
aabaa
accca

In such a matrix every row and every column form palindromes.

 

一、原题地址

点我传送

 

二、大致题意

给出一个n*m的矩阵,可以在这个矩阵上选定一个子矩阵,在这个选定的子矩阵中,每行上的元素可以随意调整。注意:是先选定子矩阵再调整矩阵中的元素,而不是先调整在确定范围。询问的是能形成回文矩阵的个数。

 

三、大致思路

首先O(n^2)的枚举左右边界[ l , r ],每一行能否形成回文串是很好判断的,只需要看在[ l , r ]范围内出现次数为奇数的数的个数是否符合就可以了。关键是列上的回文串无法快速的处理,这里就需要引入Manachar(马拉车算法)。这样就可以O(n)的处理出字符串上每个位置对答案的贡献,利用马拉车算法中点的半径p[ i ],显然每个半径长度对答案的贡献是+1的。简单来说就是将每一行当成是一个字符串中的一个小字符,然后我们试图去跑一个回文出来。

对于列上的回文,在判断两行是否相同时,我们考虑的是这两行的26个字母数量全部相同,这点也很好理解。

 

四、代码

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<map>
using namespace std;
typedef long long LL;



const int MAXN = 250;
char mmp[MAXN + 5][MAXN + 5];
int a[MAXN<<1 + 5][26], tot[MAXN<<1 + 5];
int n,m;
LL ans;
bool cmp(int x, int y)
{
	if( tot[x] > 1 || tot[y] > 1 )
        return false;
	for(int i=0;i<26;i++)
    {
        if( a[x][i]!= a[y][i] )
        {
            return false;
        }
    }
	return true;
}

LL p[MAXN*2+5];
int manacher()
{
	int i;
	int len=n;
	len++;len<<=1;
	LL ret=0,mx=0,id=0;
	for(i=1;i<len;i++)
	{
		if(mx>i)p[i]=min(p[id*2-i],mx-i);
		else p[i]=1;
		int o=i;
		while(i-p[i]>0&&i+p[i]<len&&cmp(i-p[i],i+p[i]))
        {
            p[i]++;o++;
        }
        if(tot[i]>1)p[i]=1;
		if(mx<p[i]+i)mx=p[i]+i,id=i;
		ret=max(ret,p[i]);
		ans+=(p[i])/2;
	}
	return ret-1;
}


int main()
{
	scanf("%d%d", &n, &m);
	for(int i=0;i<n;i++) scanf("%s", mmp[i]);

	for(int i=0;i<m;i++)
    {
        for(int j=0;j<n;j++)
        {
            for(int k=0;k<26;k++)
            {
                a[(j+1)<<1][k]=tot[(j+1)<<1]=0;
            }
        }
        for(int j=i;j<m;j++)
        {
            for(int k=0;k<n;k++)
            {
                if(a[(k+1)<<1][mmp[k][j]-'a']&1) tot[(k+1)<<1]--;
                else tot[(k+1)<<1]++;
                a[(k+1)<<1][mmp[k][j]-'a']++;
            }
            manacher();
        }
    }
	printf("%lld\n", ans);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值