题目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;
}
原文地址:https://www.cnblogs.com/xyqhello/p/3618574.html