2023-11-18:用go语言,如果一个正方形矩阵上下对称并且左右对称,对称的意思是互为镜像, 那么称这个正方形矩阵叫做神奇矩阵。 比如 : 1 5 5 1 6 3 3 6 6 3 3 6 1 5
2023-11-18:用go语言,如果一个正方形矩阵上下对称并且左右对称,对称的意思是互为镜像,
那么称这个正方形矩阵叫做神奇矩阵。
比如 :
1 5 5 1
6 3 3 6
6 3 3 6
1 5 5 1
这个正方形矩阵就是神奇矩阵。
给定一个大矩阵n*m,返回其中神奇矩阵的数目。
1 <= n,m <= 1000。
来自左程云。
答案2023-11-18:
go,c++,c的代码用灵捷3.5编写,go和c++有修改。
具体步骤如下:
1.通过输入获取大矩阵的大小n和m。
2.将输入的数据按行列填充到数组arr中。
3.根据行遍历,对每一行调用manacher函数进行回文串的预处理。该函数会在rp数组中保存每个位置向右的回文长度。
4.根据列遍历,对每一列调用manacher函数进行回文串的预处理。该函数会在cp数组中保存每个位置向下的回文长度。
5.遍历所有内部的行和列,计算每个位置上、下、左、右四个方向上的回文长度,并取其最小值作为当前位置的enlarge值。
6.统计enlarge数组中每个奇数行、奇数列位置的值除以2的结果,作为神奇矩阵的数量。
7.统计enlarge数组中每个偶数行、偶数列位置的值减去1后除以2的结果,再累加到神奇矩阵的数量。
8.返回神奇矩阵的数量作为结果。
总的时间复杂度:O(n * m * log(min(n, m))),其中n为矩阵的行数,m为矩阵的列数。主要耗时的是manacher函数的预处理过程,而manacher函数的时间复杂度为O(log(min(n, m)))。
总的额外空间复杂度:O(n * m),需要额外的数组保存回文长度。
go完整代码如下:
package main
import (
"fmt"
)
const MAXN = 1001
var log2 [(MAXN<<1 | 1) + 1]int
var arr [MAXN<<1 | 1][MAXN<<1 | 1]int
var rp [MAXN<<1 | 1][MAXN<<1 | 1]int
var cp [MAXN<<1 | 1][MAXN<<1 | 1]int
var enlarge [MAXN<<1 | 1][MAXN<<1 | 1]int
var rmq [MAXN<<1 | 1][MAXN<<1 | 1]int
var s [MAXN<<1 | 1]int
var p [MAXN<<1 | 1]int
var n, m int
func init() {
for k, j := 0, 1; j <= (MAXN<<1 | 1); j++ {
if 1<<(k+1) <= j {
k++
}
log2[j] = k
}
}
func main() {
inputs := []int{5, 5,
4, 2, 4, 4, 4,
3, 1, 4, 4, 3,
3, 5, 3, 3, 3,
3, 1, 5, 3, 3,
4, 2, 1, 2, 4}
ii := 0
n = inputs[ii]
ii++
m = inputs[ii]
ii++
for i, r := 0, 1; i < n; i, r = i+1, r+2 {
for j, c := 0, 1; j < m; j, c = j+1, c+2 {
arr[r][c] = inputs[ii]
ii++
}
}
n = n*2 + 1
m = m*2 + 1
fmt.Println(number())
}
func number() int {
for row := 0; row < n; row++ {
manacher(row, 0, 0, 1)
}
for col := 0; col < m; col++ {
manacher(0, col, 1, 0)
}
for row := 1; row < n-1; row++ {
rowRmq(row)
for col := 1; col < m-1; col++ {
l := 1
r := min(min(row+1, n-row), min(col+1, m-col))
find := 1
for l <= r {
m := (l + r) / 2
if query(col-m+1, col+m-1) >= m {
find = m
l = m + 1
} else {
r = m - 1
}
}
enlarge[row][col] = find
}
}
for col := 1; col < m-1; col++ {
colRmq(col)
for row := 1; row < n-1; row++ {
l := 1
r := min(min(row+1, n-row), min(col+1, m-col))
find := 1
for l <= r {
m := (l + r) / 2
if query(row-m+1, row+m-1) >= m {
find = m
l = m + 1
} else {
r = m - 1
}
}
enlarge[row][col] = min(enlarge[row][col], find)
}
}
ans := 0
for row := 1; row < n-1; row += 2 {
for col := 1; col < m-1; col += 2 {
ans += enlarge[row][col] / 2
}
}
for row := 2; row < n-1; row += 2 {
for col := 2; col < m-1; col += 2 {
ans += (enlarge[row][col] - 1) / 2
}
}
return ans
}
func manacher(row int, col int, radd int, cadd int) {
limit := 0
for r, c := row, col; r < n && c < m; r, c = r+radd, c+cadd {
s[limit] = arr[r][c]
limit++
}
C := -1
R := -1
for i := 0; i < limit; i++ {
p[i] = R
if i < R {
p[i] = min(p[2*C-i], R-i)
} else {
p[i] = 1
}
for i+p[i] < limit && i-p[i] > -1 && s[i+p[i]] == s[i-p[i]] {
p[i]++
}
if i+p[i] > R {
R = i + p[i]
C = i
}
}
var fill *[2003][2003]int
if cadd == 1 {
fill = &rp
} else {
fill = &cp
}
for i, r, c := 0, row, col; i < limit; i++ {
fill[r][c] = p[i]
r += radd
c += cadd
}
}
func rowRmq(row int) {
for i := 0; i < m; i++ {
rmq[i][0] = cp[row][i]
}
for j := 1; (1 << j) <= m; j++ {
for i := 0; i+(1<<j)-1 < m; i++ {
rmq[i][j] = min(rmq[i][j-1], rmq[i+(1<<(j-1))][j-1])
}
}
}
func colRmq(col int) {
for i := 0; i < n; i++ {
rmq[i][0] = rp[i][col]
}
for j := 1; (1 << j) <= n; j++ {
for i := 0; i+(1<<j)-1 < n; i++ {
rmq[i][j] = min(rmq[i][j-1], rmq[i+(1<<(j-1))][j-1])
}
}
}
func query(l int, r int) int {
k := log2[r-l+1]
return min(rmq[l][k], rmq[r-(1<<k)+1][k])
}
func min(a, b int) int {
if a < b {
return a
}
return b
}

c++完整代码如下:
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 1001;
int log22[(MAXN << 1 | 1) + 1];
int arr[MAXN << 1 | 1][MAXN << 1 | 1];
int rp[MAXN << 1 | 1][MAXN << 1 | 1];
int cp[MAXN << 1 | 1][MAXN << 1 | 1];
int enlarge[MAXN << 1 | 1][MAXN << 1 | 1];
int rmq[MAXN << 1 | 1][MAXN << 1 | 1];
int s[MAXN << 1 | 1];
int p[MAXN << 1 | 1];
int n, m;
void manacher(int row, int col, int radd, int cadd);
int number();
void rowRmq(int row);
void colRmq(int col);
int query(int l, int r);
int min(int a, int b);
void init() {
for (int k = 0, j = 1; j <= (MAXN << 1 | 1); j++) {
if (1 << (k + 1) <= j) {
k++;
}
log22[j] = k;
}
}
int number() {
for (int row = 0; row < n; row++) {
manacher(row, 0, 0, 1);
}
for (int col = 0; col < m; col++) {
manacher(0, col, 1, 0);
}
for (int row = 1; row < n - 1; row++) {
rowRmq(row);
for (int col = 1; col < m - 1; col++) {
int l = 1;
int r = min(min(row + 1, n - row), min(col + 1, m - col));
int find = 1;
while (l <= r) {
int mid = (l + r) / 2;
if (query(col - mid + 1, col + mid - 1) >= mid) {
find = mid;
l = mid + 1;
}
else {
r = mid - 1;
}
}
enlarge[row][col] = find;
}
}
for (int col = 1; col < m - 1; col++) {
colRmq(col);
for (int row = 1; row < n - 1; row++) {
int l = 1;
int r = min(min(row + 1, n - row), min(col + 1, m - col));
int find = 1;
while (l <= r) {
int mid = (l + r) / 2;
if (query(row - mid + 1, row + mid - 1) >= mid) {
find = mid;
l = mid + 1;
}
else {
r = mid - 1;
}
}
enlarge[row][col] = min(enlarge[row][col], find);
}
}
int ans = 0;
for (int row = 1; row < n - 1; row += 2) {
for (int col = 1; col < m - 1; col += 2) {
ans += enlarge[row][col] / 2;
}
}
for (int row = 2; row < n - 1; row += 2) {
for (int col = 2; col < m - 1; col += 2) {
ans += (enlarge[row][col] - 1) / 2;
}
}
return ans;
}
void manacher(int row, int col, int radd, int cadd) {
int limit = 0;
for (int r = row, c = col; r < n && c < m; r += radd, c += cadd) {
s[limit] = arr[r][c];
limit++;
}
int C = -1;
int R = -1;
for (int i = 0; i < limit; i++) {
p[i] = R;
if (i < R) {
p[i] = min(p[2 * C - i], R - i);
}
else {
p[i] = 1;
}
while (i + p[i] < limit && i - p[i] > -1 && s[i + p[i]] == s[i - p[i]]) {
p[i]++;
}
if (i + p[i] > R) {
R = i + p[i];
C = i;
}
}
int(*fill)[2003];
if (cadd == 1) {
fill = rp;
}
else {
fill = cp;
}
for (int i = 0, r = row, c = col; i < limit; i++) {
fill[r][c] = p[i];
r += radd;
c += cadd;
}
}
void rowRmq(int row) {
for (int i = 0; i < m; i++) {
rmq[i][0] = cp[row][i];
}
for (int j = 1; (1 << j) <= m; j++) {
for (int i = 0; i + (1 << j) - 1 < m; i++) {
rmq[i][j] = min(rmq[i][j - 1], rmq[i + (1 << (j - 1))][j - 1]);
}
}
}
void colRmq(int col) {
for (int i = 0; i < n; i++) {
rmq[i][0] = rp[i][col];
}
for (int j = 1; (1 << j) <= n; j++) {
for (int i = 0; i + (1 << j) - 1 < n; i++) {
rmq[i][j] = min(rmq[i][j - 1], rmq[i + (1 << (j - 1))][j - 1]);
}
}
}
int query(int l, int r) {
int k = log22[r - l + 1];
return min(rmq[l][k], rmq[r - (1 << k) + 1][k]);
}
int min(int a, int b) {
if (a < b) {
return a;
}
return b;
}
int main() {
init();
int inputs[] = { 5, 5,
4, 2, 4, 4, 4,
3, 1, 4, 4, 3,
3, 5, 3, 3, 3,
3, 1, 5, 3, 3,
4, 2, 1, 2, 4 };
int ii = 0;
n = inputs[ii++];
m = inputs[ii++];
for (int i = 0, r = 1; i < n; i++, r += 2) {
for (int j = 0, c = 1; j < m; j++, c += 2) {
arr[r][c] = inputs[ii++];
}
}
n = n * 2 + 1;
m = m * 2 + 1;
cout << number() << endl;
return 0;
}

c完整代码如下:
#include <stdio.h>
#define MAXN 1001
int log2Arr[(MAXN << 1 | 1) + 1];
int arr[MAXN << 1 | 1][MAXN << 1 | 1];
int rp[MAXN << 1 | 1][MAXN << 1 | 1];
int cp[MAXN << 1 | 1][MAXN << 1 | 1];
int enlarge[MAXN << 1 | 1][MAXN << 1 | 1];
int rmq[MAXN << 1 | 1][MAXN << 1 | 1];
int s[MAXN << 1 | 1];
int p[MAXN << 1 | 1];
int n, m;
void init() {
int k = 0;
for (int j = 1; j <= (MAXN << 1 | 1); j++) {
if (1 << (k + 1) <= j) {
k++;
}
log2Arr[j] = k;
}
}
int min(int a, int b) {
return (a < b) ? a : b;
}
void manacher(int row, int col, int radd, int cadd) {
int limit = 0;
for (int r = row, c = col; r < n && c < m; r += radd, c += cadd) {
s[limit] = arr[r][c];
limit++;
}
int C = -1;
int R = -1;
for (int i = 0; i < limit; i++) {
p[i] = R;
if (i < R) {
p[i] = min(p[2 * C - i], R - i);
}
else {
p[i] = 1;
}
while (i + p[i] < limit && i - p[i] > -1 && s[i + p[i]] == s[i - p[i]]) {
p[i]++;
}
if (i + p[i] > R) {
R = i + p[i];
C = i;
}
}
int(*fill)[2003];
if (cadd == 1) {
fill = rp;
}
else {
fill = cp;
}
for (int i = 0, r = row, c = col; i < limit; i++) {
fill[r][c] = p[i];
r += radd;
c += cadd;
}
}
void rowRmq(int row) {
for (int i = 0; i < m; i++) {
rmq[i][0] = cp[row][i];
}
for (int j = 1; (1 << j) <= m; j++) {
for (int i = 0; i + (1 << j) - 1 < m; i++) {
rmq[i][j] = min(rmq[i][j - 1], rmq[i + (1 << (j - 1))][j - 1]);
}
}
}
void colRmq(int col) {
for (int i = 0; i < n; i++) {
rmq[i][0] = rp[i][col];
}
for (int j = 1; (1 << j) <= n; j++) {
for (int i = 0; i + (1 << j) - 1 < n; i++) {
rmq[i][j] = min(rmq[i][j - 1], rmq[i + (1 << (j - 1))][j - 1]);
}
}
}
int query(int l, int r) {
int k = log2Arr[r - l + 1];
return min(rmq[l][k], rmq[r - (1 << k) + 1][k]);
}
int number() {
for (int row = 0; row < n; row++) {
manacher(row, 0, 0, 1);
}
for (int col = 0; col < m; col++) {
manacher(0, col, 1, 0);
}
for (int row = 1; row < n - 1; row++) {
rowRmq(row);
for (int col = 1; col < m - 1; col++) {
int l = 1;
int r = min(min(row + 1, n - row), min(col + 1, m - col));
int find = 1;
while (l <= r) {
int mid = (l + r) / 2;
if (query(col - mid + 1, col + mid - 1) >= mid) {
find = mid;
l = mid + 1;
}
else {
r = mid - 1;
}
}
enlarge[row][col] = find;
}
}
for (int col = 1; col < m - 1; col++) {
colRmq(col);
for (int row = 1; row < n - 1; row++) {
int l = 1;
int r = min(min(row + 1, n - row), min(col + 1, m - col));
int find = 1;
while (l <= r) {
int mid = (l + r) / 2;
if (query(row - mid + 1, row + mid - 1) >= mid) {
find = mid;
l = mid + 1;
}
else {
r = mid - 1;
}
}
enlarge[row][col] = min(enlarge[row][col], find);
}
}
int ans = 0;
for (int row = 1; row < n - 1; row += 2) {
for (int col = 1; col < m - 1; col += 2) {
ans += enlarge[row][col] / 2;
}
}
for (int row = 2; row < n - 1; row += 2) {
for (int col = 2; col < m - 1; col += 2) {
ans += (enlarge[row][col] - 1) / 2;
}
}
return ans;
}
int main() {
init();
int inputs[] = { 5, 5,
4, 2, 4, 4, 4,
3, 1, 4, 4, 3,
3, 5, 3, 3, 3,
3, 1, 5, 3, 3,
4, 2, 1, 2, 4 };
int ii = 0;
n = inputs[ii];
ii++;
m = inputs[ii];
ii++;
for (int i = 0, r = 1; i < n; i++, r += 2) {
for (int j = 0, c = 1; j < m; j++, c += 2) {
arr[r][c] = inputs[ii];
ii++;
}
}
n = n * 2 + 1;
m = m * 2 + 1;
printf("%d\n", number());
return 0;
}

2023-11-18:用go语言,如果一个正方形矩阵上下对称并且左右对称,对称的意思是互为镜像, 那么称这个正方形矩阵叫做神奇矩阵。 比如 : 1 5 5 1 6 3 3 6 6 3 3 6 1 5的更多相关文章
- 使用C语言实现一个虚拟机
使用C语言实现一个虚拟机 2015-6-22 21:32| 发布者: joejoe0332| 查看: 2891| 评论: 0|原作者: leoxu, Serval, 社会主义好, lostTemple ...
- linux c语言编写一个shell壳
目的:我们要用c语言编写一个shell可以运行在linux机器上的. 介绍:shell所在的层次 我们要做的是操作系统,用于用户与操作系统进行交互的myhsell 思路:用户输入 一行字符串,我们先 ...
- (转)如何学好C语言,一个成功人士的心得!
zidier111发表于 2013-1-26 08:59:05 今 天,我能够自称是一个混IT的人,并能以此谋生,将来大家能一次谋生,都要感谢两个人:克劳德.香农和约翰.冯.诺依曼,是他们发现了所 ...
- 怎样学好C语言,一个成功人士的心得!
今天,我能够自称是一个混IT的人,并能以此谋生,将来大家能一次谋生,都要感谢两个人:克劳德.香农和约翰.冯.诺依曼,是他们发现了全部的数字化信息,不论是一段程序,一封email,一部电影都是用一连串的 ...
- 用C语言写一个“事件”的模拟程序
源:用C语言写一个“事件”的模拟程序 Example.c //定义一个函数指针 func int (*func) (void); //调用该函数相当于触发了事件. //该事件触发后,会检查函数指针fu ...
- 用C语言编写一个简单的词法分析程序
问题描述: 用C或C++语言编写一个简单的词法分析程序,扫描C语言小子集的源程序,根据给定的词法规则,识别单词,填写相应的表.如果产生词法错误,则显示错误信息.位置,并试图从错误中恢复.简单的恢复方法 ...
- 用Go语言实现一个简单的聊天机器人
一.介绍 目的:使用Go语言写一个简单的聊天机器人,复习整合Go语言的语法和基础知识. 软件环境:Go1.9,Goland 2018.1.5. 二.回顾 Go语言基本构成要素:标识符.关键字.字面量. ...
- golang学习笔记18 用go语言编写移动端sdk和app开发gomobile
golang学习笔记18 用go语言编写移动端sdk和app开发gomobile gomobile的使用-用go语言编写移动端sdk和app开发https://blog.csdn.net/u01249 ...
- C语言学习一个月后感想
C语言学习一个月后感想 感谢李晓东老板及计算机工程师联盟的学长学姐和某神秘同级同学的辛勤指导,感谢宋雨田的督促和陪伴. 初识C的1..体会 我本以为凭借瓜皮思维和花里胡哨操作可以让我熟练地学习语言,现 ...
- 2017.11.13 在C语言中是否能用函数实现模块化程序设计
第七章 用函数实现模块化程序设计 (1)为什么要用函数? @function既是函数也是功能.函数就是用来完成一定功能的的(函数就是功能),函数名就是给这个功能起一个名字,一个C程序可由一个主函数和若 ...
随机推荐
- .NET周刊【7月第5期 2023-07-30】
国内文章 PaddleSharp:跨越一年的版本更新与亮点 https://www.cnblogs.com/sdflysha/p/20230724-paddlesharp-in-a-year.html ...
- FJOI2022 游记
2022.3.28 省选延期,延到了4.16 2022.4.11 省选又延期,延到了5.2 FJOI 要回来了!! Day -7 开始停课了 QwQ Day -6 打摆 Day -5 打摆 不行,我不 ...
- 2023-08-04:村里面一共有 n 栋房子 我们希望通过建造水井和铺设管道来为所有房子供水。 对于每个房子 i,我们有两种可选的供水方案: 一种是直接在房子内建造水井 成本为 wells[i -
2023-08-04:村里面一共有 n 栋房子 我们希望通过建造水井和铺设管道来为所有房子供水. 对于每个房子 i,我们有两种可选的供水方案: 一种是直接在房子内建造水井 成本为 wells[i - ...
- 【python】调用钉钉机器人发起通知
有时候需要做个某些服务的状态监控,用钉钉机器人发通知挺方便的.可以用shell脚本配合crontab检测状态,检测到异常就调用python脚本发起告警. python内容 此处用的python3,需要 ...
- C#性能优化-树形结构递归优化
前言 大家好,我是wacky,最近在工作中遇到一个有趣的问题,同事反馈说WPF中有一个树形结构的集合,在加载时会直接报堆栈溢出,一直没时间(懒得)看,导致很久了也没人解决掉.于是,组长就把这个&quo ...
- 「学习笔记」扩展 KMP(Z 函数)
对于个长度为 \(n\) 的字符串 \(s\).定义 \(z[i]\) 表示 \(s\) 和 \(s[i,n-1]\)(即以 \(s[i]\) 开头的后缀)的最长公共前缀(LCP)的长度.\(z\) ...
- Web应用防火墙--规则防护
一.什么是Web应用防火墙? Web应用防火墙对网站.APP的业务流量安全及合规性保护,对业务流量的识别恶意特征提取.分析识别出恶意流量并进行处理, 将正常安全的流量回源到业务服务器, 保护网站核心业 ...
- 如何将GitLab仓库同步到GitHub和Gitee?
作者:西瓜程序猿 主页传送门:https://www.cnblogs.com/kimiliucn 前言 在之前写的[Kimi.RocketMQ.NET]开源项目中,代码我是放在自己搭建的GitLab服 ...
- 【解惑】时间规划,Linq的Aggregate函数在计算会议重叠时间中的应用
在繁忙的周五,小悦坐在会议室里,面前摆满了各种文件和会议安排表.她今天的工作任务是为公司安排下周的50个小会议,这让她感到有些头疼.但是,她深吸了一口气,决定耐心地一个一个去处理. 首先,小悦仔细地收 ...
- 在Go中如何实现并发
Go语言的并发机制是其强大和流行的一个关键特性之一.Go使用协程(goroutines)和通道(channels)来实现并发编程,这使得编写高效且可维护的并发代码变得相对容易.下面是Go的并发机制的详 ...