zoukankan      html  css  js  c++  java
  • POJ 2185 kmp

    题目链接:http://poj.org/problem?id=2185

    题意:给出一个R*C(10000 * 75)的矩形字符串,然你求最小的不严格重复矩阵,比如,ABA,最小的重复矩阵是AB,经过复制ABAB,可以把ABA完全覆盖掉。

    题解:

      题意很好理解,首先我们应该清楚,最小重复字串一定实在左上角。我们可以找到宽的最小共同重复串,然后,我们就可以对高进行kmp。答案即为w*h的值。对于宽,我们可以暴力找,枚举每一行的所有起点为0的字串,判断该长度是否满足重复,然后,我们所有行的最小共同的重复字串,即为宽w,对于高,只需要进行一次kmp求最小重复字串即可。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn = 1e4 + 15;
    char s[maxn][80], T[80];
    int net[maxn];
    int bit[80];
    int R, C;
    int main()
    {
        int ans = 0;
        scanf("%d%d", &R, &C);
        for(int i = 0; i < C; i++) bit[i] = 0;
        for(int i = 0; i < R; i++)
        {
            scanf("%s", s[i]);
            strcpy(T, s[i]);
            for(int j = C - 1; j >= 1; j--)
            {
                T[j] = 0;
                int x = 0, y = 0;
                for(; s[i][y]; x++, y++)
                {
                    if(!T[x]) x = 0;
                    if(T[x] != s[i][y]) break;
                }
                if(!s[i][y]) bit[j]++;
            }
        }
        for(int i = 1; i < C; i++)
            if(bit[i] == R)
            {
                ans = i;
                break;
            }
        if(!ans) ans = C;
        for(int i = 0; i < R; i++)
            s[i][ans] = 0;
        net[0] = -1;
        int j = 0, k = -1;
        while(j < R)
        {
            if(k == -1 || !strcmp(s[k], s[j])) net[++j] = ++k;
            else
                k = net[k];
        }
        printf("%d
    ", (R - net[R])*ans); //行列相乘即为最终结果
        return 0;
    }

    有一个优化:http://poj.org/showmessage?message_id=168710

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn = 1e4 + 15;
    char s[maxn][80], T[80];
    int net[maxn];
    int bit[80];
    int R, C;
    int main()
    {
        int ans = 0;
        scanf("%d%d", &R, &C);
        for(int i = 0; i < C; i++) bit[i] = 0;
        for(int i = 0; i < R; i++)
        {
            scanf("%s", s[i]);
            strcpy(T, s[i]);
            for(int j = C - 1; j >= 1; j--)
            {
                T[j] = 0;
                int x = 0, y = 0;
                for(; s[i][y]; x++, y++)
                {
                    if(!T[x]) x = 0;
                    if(T[x] != s[i][y]) break;
                }
                if(!s[i][y]) bit[j]++;
            }
        }
        for(int i = 1; i < C; i++)
            if(bit[i] == R)
            {
                ans = i;
                break;
            }
        if(!ans) ans = C;
        net[0] = -1;
        int j = 0, k = -1;
        while(j < R)
        {
            if(k == -1 || !strcmp(s[k], s[j])) net[++j] = ++k;
            else
                k = net[k];
        }
        printf("%d
    ", (R - net[R])*ans); //行列相乘即为最终结果
        return 0;
    }

     

  • 相关阅读:
    20161203
    20161201
    20161128课堂笔记
    数组排序 (选择排序、冒泡排序、插入排序、希尔排序)
    编一个多用户登陆程序
    20161115课堂笔记
    20161114课堂笔记
    20161111课堂笔记
    面试常见问题
    java 基础第一周
  • 原文地址:https://www.cnblogs.com/pealicx/p/7421463.html
Copyright © 2011-2022 走看看