• 玲珑杯”ACM比赛 Round #4 1054


    http://www.ifrog.cc/acm/problem/1054

    问删除一个字符后的最小循环节是多少、

    比赛的时候想不出,不知道怎么暴力。

    赛后看了别人代码才晓得。唉,还以为自己字符串还不错,但是变了一点点就不懂了。

    1、可以暴力枚举循环节长度i,必要条件是(lenstr - 1) % i == 0。这是必须的,因为必须是倍数,关于约数的个数:(不大)

    http://vfleaking.blog.163.com/blog/static/174807634201341913040467/

    其实复杂度什么的都是浮云?咱还是关心实际数字吧 >_<
    10^9以内最大的Highly composite number是735134400,约数个数为1344个。(1000)
    int32以内最大的Highly composite number是2095133040,约数个数为1600个。(1000)
    10^18以内最大的Highly composite number是897612484786617600,约数个数为103680个。(10^5)
    int64以内最大的Highly composite number是9200527969062830400,约数个数为161280个。(10^5)
     

    2、怎么判断这个循环节可行呢?

    比如我有Habcabcabc,枚举了3,那么怎么判断3是可行的呢?

    关键是利用扫描的思想。

    记录cnt表示匹配了多少个,那么只需匹配6个就证明可行。

    第一,'H' != 'c',cnt设置为0,表明一个也没匹配成功。

    第二步,'a'和'a'成功。然后第三步'b'和'b'成功,'c'和'c'成功,竟然能变成枚举了"abc",然后就这样一直枚举下去。

    这和我以前写的不同,Hab|cab|cab|c,我以前的是很死板的分段,现在这个不但能满足要求(求出正常的解,就是abcabcabc这样一样能枚举3是ans),还能忽视某些值,例如这里忽视了H。。

    所以说怎么用O(n)判断可不可行,也是有技巧的。(这个能求出满足循环节为3的最大长度)

    但是还是不能满足题目,例如aabaa,只能求出是循环节是1的时候长度是2,怎么模拟删除一个字符呢?

    答案是把字符串写两次。变成aabaa|aabaa。。就是相当于反向的字符串了,那么既然循环,反向或者旋转与否不影响。

    例如aHbcabcabc|aHbcabcabc。

    这个变成了bcabcabca。。ans = 3;

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    const int maxn = 100001 + 20;
    char str[maxn * 2];
    void work() {
        int lenstr;
        cin >> lenstr;
        cin >> str + 1;
        int t = 1;
        for (int i = lenstr + 1; i <= 2 * lenstr; ++i) {
            str[i] = str[t++];
        }
        str[2 * lenstr + 1] = '';
        int ans = lenstr - 1;
        t = lenstr - 1;
        for (int i = 1; i <= t; ++i) {
            if (t % i != 0) continue;
            int cnt = 0;
            for (int j = 1; j + i <= 2 * lenstr; ++j) {
                if (str[j] == str[j + i]) {
                    cnt++;
                    if (cnt == t - i) {
                        cout << t / i << endl;
                        return;
                    }
                } else cnt = 0;
            }
        }
        cout << 1 << endl;
        return;
    }
    
    int main() {
    #ifdef local
        freopen("data.txt","r",stdin);
    #endif
        IOS;
        int t;
        cin >> t;
        while (t--) work();
        return 0;
    }
  • 相关阅读:
    malloc
    排序算法学习笔记(三)-- 快速排序
    排序算法学习笔记(二)-- 归并排序
    排序算法学习笔记(一)-- 冒泡排序,选择排序,插入排序,希尔排序
    网络协议笔记
    域名和IP地址并用的理由
    WebSocket协议介绍
    Ajax概念
    共享密钥加密、公开密钥加密及HTTPS混合加密
    HTTP缺点
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6033954.html
Copyright © 2020-2023  润新知