SPOJ - PLSQUARE

【题目链接】 点击打开链接

【题意】给了一个n*n的字符矩阵,求最大的k使得存在一个k*k的子矩阵,满足这个k*k的矩阵里横和竖的所有字符串都是回文串。

【解题方法】Wannafly群赛题。详细解题方法看这里点击打开链接

                      大致的方法就是分为两个dp,第一个dp处理对于行和列的任意一个下标处理这两个下标之间的字符串是否为回文串,第二步的dp是枚举一个矩形的坐标和他延伸的长度为k的字串,判断是否为回文串,并更新dp值。然后处理完这个过程之后,我们再枚举行列,长度更新最后的最大答案。这个dp比较绕,文字比较难描述,视频已经讲解的很清楚了。

【复杂度】 O(n^3)

【AC代码】

//
//Created by just_sort 2016/12/30
//Copyright (c) 2016 just_sort.All Rights Reserved
//

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream> //isstringstream
#include <iostream>
#include <algorithm>
using namespace std;
using namespace __gnu_pbds;
typedef long long LL;
typedef pair<int, LL> pp;
#define REP1(i, a, b) for(int i = a; i < b; i++)
#define REP2(i, a, b) for(int i = a; i <= b; i++)
#define REP3(i, a, b) for(int i = a; i >= b; i--)
#define MP(x, y) make_pair(x,y)
const int maxn = 1000010;
const int maxm = 2e5;
const int maxs = 10;
const int INF = 1e9;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>order_set;
//head
int n;
char s[222][222];
int r[222][222][222], c[222][222][222], rdp[222][222][222], cdp[222][222][222];

int main()
{
    while(scanf("%d", &n) != EOF)
    {
        memset(r, 0, sizeof(r));
        memset(c, 0, sizeof(c));
        memset(rdp, 0, sizeof(rdp));
        memset(cdp, 0, sizeof(cdp));
        REP2(i, 1, n) scanf("%s", s[i] + 1);
        REP2(i, 1, n){
            REP3(j, n, 1){
                REP2(k, j, n){
                    if(s[i][j] == s[i][k]){
                        if(j + 1 >= k - 1) r[i][j][k] = 1;
                        else if(r[i][j+1][k-1]) r[i][j][k] = 1;
                    }
                }
            }
        }
        REP2(j, 1, n){
            REP3(i, n, 1){
                REP2(k, i, n){
                    if(s[i][j] == s[k][j]){
                        if(i + 1 >= k - 1){
                            c[j][i][k] = 1;
                        }
                        else if(c[j][i+1][k-1]){
                            c[j][i][k] = 1;
                        }
                    }
                }
            }
        }
        REP3(i, n, 1){
            REP2(j, 1, n){
                REP2(k, 1, n + 1 - j){
                    if(r[i][j][j + k - 1]){
                        rdp[i][j][k] = rdp[i+1][j][k] + 1;
                    }else{
                        rdp[i][j][k] = 0;
                    }
                }
            }
        }
        REP3(j, n, 1){
            REP2(i, 1, n){
                REP2(k, 1, n + 1 - i){
                    if(c[j][i][i + k - 1]){
                        cdp[j][i][k] = cdp[j+1][i][k] + 1;
                    }
                    else{
                        cdp[j][i][k] = 0;
                    }
                }
            }
        }
        int ans = 0;
        REP2(i, 1, n){
            REP2(j, 1, n){
                REP2(k, 1, n){
                    if(rdp[i][j][k] >= k && cdp[j][i][k] >= k){
                        ans = max(ans, k);
                    }
                }
            }
        }
        cout << ans << endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值