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

【题意】给了一个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;
}