• 题目1555:重复子串


    题目描述:

    给定一个由小写字母组成的字符串,求它的所有连续子串中,出现过至少两次,且至少有一对出现的重复子串是不重合的连续子串个数。
    如给定字符串aaaa,aa和a,符合条件,aaa不符合条件(出现重合),故答案为2。

    输入:

    输入包含多组测试用例,每组测试用例包含一个字符串,由小写字母组成,其长度不大于1000。

    输出:

    对于每组测试数据,输出一个整数,代表符合条件的子串个数。

    样例输入:
    aaaa
    aaa
    样例输出:
    2
    1

    刚开始的时候,想到遍历每个字符子串,比如从位置1开始,依次遍历长度从1到n的子串,需要N^2。然后从位置2开始,依次遍历长度从1到n的子串,需要N^2。如果依次遍历完,总共O(N^3).字符串最长为1000,明显超过10^7数量级。就没有向下思考。
    但是,仔细观察题目要求,会发现字符串是由小写字母组成的。那么如果长度很长,那么必然会有大量的重复字符串。而且,题目要求我们只需要找出满足条件的字符子串种类型,所以,如果我们采用枚举遍历,将曾经遍历过的字符子串标记出来,那么以后碰见这样的字符子串,就不需要重复遍历了。这样,必然可以讲数量级直接降到很低。
    然后我们观察,如果i开始,长度为l的字符子串没有匹配,那么i开始,长度为l+1的,直接break,跳到i+1。这样又可以剪枝。
    思路:穷举+剪枝,(1).枚举起点i和长度L,mark[i][L]表示这个字符串是否处理过,处理过不再处理,(2).若i位置上长L的串不可以,则更长的串也不可以,直接break L到下一个i

    AC代码:
    #include <stdio.h>
    #include <string.h>
    
    const int MAX = 1002;
    
    int main()
    {
        bool mark[MAX][MAX];
        char str[MAX];
        while(scanf("%s", str) != EOF)
        {
            int len = strlen(str);
            for(int i = 0; i <= len ; i++)
            {
                for(int j = 0; j <= len; j++)
                    mark[i][j] = false;
            }
            int ans = 0;
            for(i = 0; i < len; i++)
            {
                //如果i开始,j的长度的子串超过了字符串长度,那么,应该直接跳过。
                for(int j = 1; j < len && i + j <= len; j++)
                {
                    int  hasMatch = 0;
                    //如果从i开始,长度为j的字符串子串检查过,那么直接开始j+1的子串检查
                    if(mark[i][j] == true)
                        continue;
                    //对从i开始,长度为j的字符串子串进行遍历。
                    for(int k = i + j; k <= len - j; k ++)
                    {
                        //对已经标记过得子串(k,j),说明以前已经被匹配过,就不能再次进行匹配了
                        if(mark[k][j] == true)
                            continue;
    
                        if(strncmp(str + i, str + k, j) == 0)
                        {
                            mark[k][j]    = true;
                            hasMatch    = 1;
                        }
                    }
                    //遍历一遍之后进行统计
                    mark[i][j] = true;
                    ans += hasMatch;
                    if(hasMatch == 0)
                        break;
                }
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    去掉Form产生的空行
    转:Override错误
    面试
    JMF获取设备列表失败,获取视频设备失败?
    jquery 插件ztree的应用动态加载树节点数据
    关于Struts2上传文件
    未能解析引用的程序集“”,因为它对不在当前目标框架“”具有依赖关系。请删除对不在目标框架中的程序集的引用,或考虑重新确定项目的目标。 Kevin
    The diffrence between Cast() and OfType() Kevin
    “System.Collections.Generic.IEnumerable<decimal>”不包含“ToArray”的定义,并且找不到可接受类型为“System.Collections.Generic.IEnumerable<decimal>”的第一个参数的扩展方法“ToArray” Kevin
    partial关键字的含义和使用 Kevin
  • 原文地址:https://www.cnblogs.com/xyqhello/p/3618574.html
Copyright © 2020-2023  润新知