“新智认知”杯上海高校程序设计竞赛暨第十七届上海大学程序设计春季联赛 B CSL的密码

博客分享牛客竞赛题解题思路,数据随机生成时,子串长度大于一定值默认不同,小于则可扔set或hash。还给出标准AC代码,提到第二份代码提交C++11不稳定,C++14可过。同时总结自身问题,如int转longlong运算、substr取子串、min函数类型比较等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:https://ac.nowcoder.com/acm/contest/551/C

解题思路:

数据随机生成,当子串大于长度一定值默认认为不相同。

小于这个默认值的,要么扔进set,要么hash

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<set>
#define ull unsigned long long
#define ll long long

using namespace std;

const int N = 1e5+5;

set<ull>cnt;
char s[N];

int main()
{
    ll n,m;
    while (~scanf("%lld %lld",&n,&m)){
        scanf("%s",s);
        //ll ans = (n-m+1)*(n-m+2)/2;
        ull Hash=0;
        ll ans_lower_15=0,ans=0;
        for (int i=m;i<=min(15LL,n);i++){///子串长度
            cnt.clear();
            for (int j=0;j<=n-i;j++){///子串起点
                ull Hash = 0;
                for (int k=j;k<(j+i);k++)///求出对应子串哈希值
                    Hash = Hash*27+(s[k]-'a'+1);
                cnt.insert(Hash);
            }
            ans_lower_15 += cnt.size();
        }
        ans += ans_lower_15;
        if (n>15 && m<=15) ans += (n-16+1)*(n-16+2)/2;
        if (n>15 && m>15) ans = (n-m+1)*(n-m+2)/2;
        printf("%lld\n",ans);
    }
    return 0;
}




标准AC代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
set<string>s;
int main()
{
    ll n, m,count=0;
    string a;
    cin >> n >> m >> a;
	ll sum = (n - m + 1)*(n - m + 2) / 2;
    for (int i = m; i <= min(n,15LL); i++)
    {
        for (int j = 0; i + j - 1 < n; j++)
        {
            string temp = a.substr(j, i);
            if (s.find(temp) != s.end())
                count++;
            else
				s.insert(temp);
        }
    }
    cout << sum - count << endl;
    return 0;
}

第二份代码怎么说呢,提交C++11一会儿让过,一会儿不让过。不过尽量别像这份代码里一样用count做变量,毕竟count绿的,提交的编译器也不知道会整出什么幺蛾子。

总的来说,第二份交把人疯了。C++14可以过。

不能白被题目坑,就写几点自己的问题。

①进行int数据进行longlong运算会爆掉,当出现需要得到n*n之类的时候要注意。

②substr可以很方便的取到子串,塞入map,set什么的

③使用min函数比较int和longlong型数据会报错,把int转化为longlong就OK了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值