2018ACM校赛 D 白狼(暴力枚举)

问题 D: 白狼

时间限制: 1 Sec  内存限制: 128 MB

题目描述

三原发现了一个古老的咒语S,咒语只有两个字母o和k组成。三原深知咒语的强大威力,无奈自己只知道破解咒语的法印具有什么特性,而不知道具体的法印应该是什么。具三原手中的古卷描述,法印同咒语,也是只有o和k两个字母组成的,但是法印不应该是咒语中出现的任何一段连续的字母,而且在所有能够满足上述条件的法印中,越短的法印力量越强大,若两个法印长度相同,字典序更小的法印力量更强大,求能够破解咒语的力量最强大的法印。

输入

一行咒语,咒语长度不超过500000

输出

能够破解咒语的力量最强大的法印。

样例输入

okoko

样例输出

kk

提示

字典序最小是指对于任意两个字符串s、t,s<t当且仅当存在一个数i,j,且j<i,s1 = t1..sj = tj且si < ti

分析:

假设法印串的最后长度为 L,字符串 S 中最多包含 N-L+1 个长度为 L 的子
串。而长度为 L 的串一共有 2^L 个。若 N-L+1<2^L,则必有某个长度为 L
的串 T 不是 S 的子串。而咒语长度≤500000,因此 N-19+1<2^19,所以无
论如何,L=19 必定是一个可行的 L。因此我们只需对长度不超过 19 的子
串进行统计。将 S 转成用 01 串来表示,0 表示 k,1 表示 o,然后找出所
有长度不超过 19 的子串放入一个数组中,标记为 true。然后从小到大枚
举串 T,若!match[T],则已找到答案。

当时由于缺乏字符串相关的知识,没敢做,看了学长的解析才发现原来是个简单的暴力枚举...

把字符串转化成编码存入数组st中,st为i代表存在长度为i+1的该串,每轮枚举过后,从前往后找出不存在的串即可。

#include<bits/stdc++.h>
using namespace std;
char s[500100];
int st[(1<<19)+100];
int code(int bg,int ed)
{
    int sum=0;
    for(int i=bg; i<=ed; ++i)
    {
        if(i>bg)
            sum<<=1;
        if(s[i]==‘o‘)
            ++sum;
    }
    return sum;
}
string encode(int val,int len)
{
    string str;
    while(len--)
    {
        if(val&1)
            str.push_back(‘o‘);
        else
            str.push_back(‘k‘);
        val>>=1;
    }
    reverse(str.begin(),str.end());
    return str;
}
int main()
{
    //freopen("i.txt","r",stdin);
    scanf("%s",s);
    int n=strlen(s);
    memset(st,-1,sizeof st);
    for(int i=0; i<19; ++i)
    {
        int cnt=0;
        for(int j=0; j<n-i; ++j)
        {
            int t=code(j,j+i);
            if(st[t]!=i)
            {
                st[t]=i;
                ++cnt;
                if(cnt==1<<(i+1))
                    break;
            }
        }
        if(cnt<1<<(i+1))
            for(int j=0; j<(1<<(i+1)); ++j)
                if(st[j]!=i)
                {
                    cout<<encode(j,i+1)<<endl;
                    return 0;
                }
    }
}

原文地址:https://www.cnblogs.com/ncc62497/p/8947523.html

时间: 2024-10-06 18:46:03

2018ACM校赛 D 白狼(暴力枚举)的相关文章

NYOJ-682 小媛在努力 (郑大第六届校赛 模拟)

链接:click here 题意: 描述 在多媒体数据处理中,数据压缩算法尤为重要.小媛上完课后就想自己发明一个数据压缩算法.她想呀想,终于想到一个方法.在多媒体数据中有很多数据都是重复的,所以她想把连续相同的数据用数据出现的次数和数据本身表示.例如:1 1 1 2 3 3 3 3 3  压缩后及为3 1 1 2 5 3(表示3个1,1个2和5个3).有想法后小媛就希望把它用代码实现了.但是大家都知道小媛现在整天都忙着苦B的复习考研,连电脑都摸不到.所以她希望作为ACMer的你帮她写一下. 输入

ZJU校赛 一道计数题

题意是这样的 给定一个n*m的整数矩阵 n和m均小于1000 对这个矩阵删去任意行和列后剩余一个矩阵为M{x1,x2,,,,xm;y1,y2,,,,,yn}表示删除任意的M行N列 对于这个剩下的矩阵,我们考虑其中是否存在特殊的元素,保证这些元素是所在行最大,所在列最小的元素 且非之一. 求对于所有删法,上述元素个数之和 对10^9+7取余. 显然所有删法 有2^(n+m)种 暴力是搞不定的. 于是反过来看,矩阵的元素最多有10^6个 是不是可以考虑每一个元素对最终答案的贡献? 所谓贡献,就是它在

2016 年宁波工程学院第七届ACM校赛题解报告

2016 年宁波工程学院第七届ACM校赛题解报告 本题解代码直接为比赛代码,仅供参考. A,B,C,D,G,H,J,K,L,M 来自 Ticsmtc 同学. F 来自 Gealo 同学. E,I 来自Alex 学长. Promblem A :    Two Sum 时间限制: 1 Sec  内存限制: 64 MB 题目描述: 给出n个数,另外给出?个整数S,判断是否可以从中取出2个数,使得这两个数的和是S. 输入: 第?行有个整数T(1 <= T <= 10),代表数据组数. 对于每组数据,第

记一次校赛。。

收到的短信是11点45分签到的,比赛是12点开始,4点结束.而我的外卖竟然11点32分才到.无奈之下,随意几口,11点37分之后开始猛冲SL一楼.之后就进入了机房,找到了自己的位置,开始调试编译器..说实话,我很不习惯那键盘,用那键盘打代码速度起码下降4分之一.到了11点55分之后,一些学姐学长和工作人员都在强调一些纪律,并且准备气球(做一道题给你插上一个气球).而我的内心,已经十分的紧张了,不仅是因为那种气氛,并且我的前两次热身赛都没有很理想,经常被一道坑题卡很久很久,导致我没有去做其它的题目

swust oj 763--校门外的树 Plus(暴力枚举)

题目链接:http://acm.swust.edu.cn/problem/0763/ Time limit(ms): 1000 Memory limit(kb): 65535 西南某科技大学的校门外有N排树,每一排树的长度可能不同.每一棵树都用字符作了一个标记. 现在由于学校修建教师公寓,需要在每排树中砍一段连续的树.要求是在每一排树中砍掉的那一段树标记序列都相同. 例如第1排:ABCD,第2排BCDFF,第3排:BRCD,那么我们就可以在每一排树中砍掉CD.请注意下面测试数据的第二组,我们可以

2015 GDUT校赛

周末打了个GDUT的校赛,也是作为SCAU的一场个人排位. 比赛中竟然卡了个特判,1个半钟就切了5条了,然后一直卡. 还有其他两条可以做的题也没法做了,性格太执着对ACM来说也是错呀. 讲回正题 . A  游戏王 . 目的是集齐6张卡, 然后n个小伙伴手上持有卡num, 给出m种集合 , Stubird需要有某个集合中的卡片才能用c的花费去买这张卡片. 做法是状压dp , 开一个 dp[st] , 表示st( 0 <= st < (1<<6) ) 这个集合最小花费 . 然后开一个邻

2018bnu校赛总结

····我好菜,完全没有准确率只写了签到,完全被吊打QAQ 大概就是自己懒惰的后果吧qwq A 塞特斯玛斯塔 签到···我因为是多组样例wa了一发···· #include <bits/stdc++.h> using namespace std; char s[100010]; int main() { int t,n;scanf("%d",&t); while(t--){ scanf("%d",&n); int cnt=0; for(i

hdu5616 暴力枚举

2017-08-25 20:08:54 writer:pprp 题目简述: ? HDU 5616? n个砝码,可以放在天平左右两侧或不放? m次询问,每次询问是否可以测出给定重量? 1 ≤ n ≤ 20? 1 ≤ m ≤ 100 这道题采用枚举的思路的话实现起来还是有点困难的, 要实现的功能是对每个砝码进行处理,加到左边, 加到右边,或者是不加 看了大神的代码,感觉很巧妙, 设置了两个标记数组 vis1[2005], vis2[2005] 一个vis1用来记录当前已经可以实现的重量 另一个vis

hdu4282A very hard mathematic problem 暴力枚举

//给出k //找x,y,z使得x^z+y^z+x*y*z = k //x,y,z都为正整数x<y,z>1问有多少种方法 //当z = 2时,可以看到左边是一个完全平方 //而当z>=3时,可以暴力枚举x,y //由于k<2^31所以x<2^(31/3)枚举复杂度可以过 #include<cstdio> #include<cstring> #include<iostream> #include<cmath> using name