首页 > 代码库 > POJ 2185 二维KMP

POJ 2185 二维KMP

题意:就是让你求出最小的字符矩阵面积,这个矩阵是这个大矩阵里能够循环的,但是并不一定是全部循环相同的,部分相同也算循环,比如样例。

思路:这题挺好的,以前没有想到二维字符串数组也可以用next数组求出其循环节,现在这题正好补了这个空。

解法:把每一个字符串当做字符进行求next数组,然后求出最小的循环字符串长度,即:len-next[len]。因为以前求循环节是len/(len-next[len]),括号里面的不就是最小的循环长度嘛!

因为要求这个循环矩阵的长和宽,所以长就是每一行作为一个字符串,然后求出最小循环字符串长度;宽就是每一列作为一个字符串,也求出循环长度,相乘即为答案!

刚开始看网上好多代码没看懂,什么最公倍数啊最小覆盖啊,都没看懂博主在干嘛,其实好理解的嘛二维KMP。上面解释也很清楚了,还不理解的看代码就懂了。

#pragma comment(linker, "/STACK:1024000000,1024000000")//扩内存,因为有的题目可能要开1000*1000的数组
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#include<bitset>
#define mem(a,b) memset(a,b,sizeof(a))
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
#define llson j<<1,l,mid
#define rrson j<<1|1,mid+1,r
#define INF 6
#define maxn 10005
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
int next[maxn];
char s[maxn][maxn],str[77][maxn],ss[maxn];
int getnext(int len,char p[][maxn])
{
    int i,j;
    mem(next,0);
    next[0]=next[1]=0;
    for(i=1;i<len;i++)
    {
        j=next[i];
        while(j&&strcmp(p[i],p[j])) j=next[j];
        next[i+1]=(!strcmp(p[i],p[j])?j+1:0);
    }
    return len-next[len];
}
int main()
{
    //freopen("1.txt","r",stdin);
    int l,r,i,j;
    scanf("%d%d",&l,&r);
    for(i=0;i<l;i++)
        scanf("%s",s[i]);
    for(i=0;i<r;i++)
        for(j=0;j<l;j++)
            str[i][j]=s[j][i];//取出每一列作为新的字符串,因为宏观上要求列的循环长度
    int w=getnext(l,s);//宽
    int h=getnext(r,str);//长
    printf("%d\n",w*h);
    return 0;
}