CSL的密码

链接:https://ac.nowcoder.com/acm/contest/551/C
来源:牛客网
 

时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld

题目描述

众所周知,CSL 最喜欢的密码是 ******。于是有一天……

 

CSL的密码

 

为了改变这一点,他决定重新设定一个密码。于是他随机生成了一个很长很长的字符串,并打算选择一个子串作为新密码。他认为安全的密码长度至少为 m,那么他有多少种不同选择方式呢?两种方案不同,当且仅当选出的密码内容不同。

输入描述:  

第一行有两个整数 n 和 m ,分别表示 CSL 随机生成的字符串长度和安全的密码的最短长度。
第二行有一个长度为 n 的只含小写字母的字符串 s 表示 CSL 随机生成的字符串。

1≤m≤n≤100000

输出描述:

在一行输出一个整数,表示 CSL 能选择的方案数。

输入

9 1
abcabcabc

输出

24

备注:

除样例外,所有的测试数据的字符串的每个字符均从小写字母 a - z 等概率随机生成

 

思路:

比赛时没有做出来,赛后看别人的代码,发现有点投机取巧的意思

题目大意是让你找长度大于m的字符串有多少不同的,一般思路是直接暴力,把所有的长度大于m的字串全部找出来放入set中,输出下size就可以了,但是这样的话会T,那么你就认为如果字串的长度是大于某一个值得话,是不存在和它相同的字串的,所以直接一趟循环就求出来了,这个值的话15就可以

之所以能这么做,可能是因为那个备注

除样例外,所有的测试数据的字符串的每个字符均从小写字母 a - z 等概率随机生成

                                            随机生成

#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <set>
using namespace std;

int main()
{
    int n,m;
    long long ans=0;
    string a;
    cin>>n>>m;
    cin>>a;
    //如果长度小于15,需要判断是否重复
    for(int i=m;i<=min(15,n);i++) //字符串长度
    {
        set<string> st;
        for(int j=0;j<=n-i;j++)  //字符串起点
        {
            string t=a.substr(j,i);
            st.insert(t);
        }
        ans+=st.size();
    }    
    //长度大于15,就不需要判断了
    for(int i=max(16,m);i<=n;i++)
    {
         ans+=n-i+1;
    }
    cout<<ans<<endl;
    return 0;
}