• 题目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;
    }
  • 相关阅读:
    SpringBoot集成Mybatis
    springboot通过slf4j配置日志
    SpringBoot导入jsp依赖始终报错
    shiro小记
    阿里开发手册华山版——(编程规约篇)记录目前自己不合理的地方
    [网络流24题] 2. 太空飞行计划问题 解题报告
    LOJ 6089 小 Y 的背包计数问题 解题报告 (动态规划)
    UVA 10599 Blocks 解题报告 (动态规划)
    Comet OJ#12E Ternary String Counting 解题报告
    [WC2016]挑战NPC 解题报告
  • 原文地址:https://www.cnblogs.com/xyqhello/p/3618574.html
Copyright © 2020-2023  润新知