牛客网多校第七场 J Sudoku Subrectangles

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zy704599894/article/details/81544049

链接:https://www.nowcoder.com/acm/contest/145/J
来源:牛客网
 

You have a n * m grid of characters, where each character is an English letter (lowercase or uppercase, which means there are a total of 52 different possible letters).

A nonempty subrectangle of the grid is called sudoku-like if for any row or column in the subrectangle, all the cells in it have distinct characters.

How many sudoku-like subrectangles of the grid are there?

输入描述:

The first line of input contains two space-separated integers n, m (1 ≤ n, m ≤ 1000).

The next n lines contain m characters each, denoting the characters of the grid. Each character is an English letter (which can be either uppercase or lowercase).

输出描述:

Output a single integer, the number of sudoku-like subrectangles.

示例1

输入

复制

2 3
AaA
caa

输出

复制

11

题意:给出一个字符矩阵,只包含大小写字母,问有多少个子矩阵为字符数独(任意一行或一列没有重复字符)。

注意到一共只有52个不同字符,如果枚举每一个左上端点,然后做52*52的暴力一定可以得出答案但是也一定会超时,所以先预处理出每一个位置可以向右和向下延伸的最大值,然后还是n*m遍历所有左端点,但是计数复杂度优化成了52。

扫描二维码关注公众号,回复: 3411645 查看本文章
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
using namespace std;
#define ll long long
const int maxm = 1005;
int r[maxm][maxm], c[maxm][maxm], s[maxm][maxm], flag[maxm];
char str[maxm][maxm];
int main()
{
	int n, i, j, k, sum, m, cnt = 0;
	ll ans = 0;
	scanf("%d%d", &n, &m);
	for (i = 1;i <= n;i++)
		scanf("%s", str[i] + 1);
	for (i = 1;i <= n;i++)
	{
		for (j = 1;j <= m;j++)
		{
			cnt++;
			for (k = j;k <= min(j + 52 - 1, m);k++)
			{
				if (flag[str[i][k]] == cnt)
					break;
				flag[str[i][k]] = cnt;
			}
			r[i][j] = k - j;
			cnt++;
			for (k = i;k <= min(i + 52 - 1, n);k++)
			{
				if (flag[str[k][j]] == cnt)
					break;
				flag[str[k][j]] = cnt;
			}
			c[i][j] = k - i;
		}
	}
	for (i = 1;i <= n;i++)
	{
		for (j = 1;j <= m;j++)
		{
			s[i][j] = c[i][j];
			int e = j + r[i][j] - 1, now;
			for (k = j + 1;k <= e;k++)
				s[i][k] = min(s[i][k - 1], c[i][k]);
			ans += r[i][j];
			e = c[i][j] + i - 1, now = j + r[i][j] - 1;
			for (k = i + 1;k <= e;k++)
			{
				now = min(now, j + r[k][j] - 1);
				while (s[i][now] < k - i + 1 && now >= j)
					now--;
				if (now < j) break;
				ans += now - j + 1;
			}
		}
	}
	printf("%lld\n", ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zy704599894/article/details/81544049
今日推荐