玲珑杯”ACM比赛 Round #4 1054 - String cut 暴力。学到了扫描的另一种思想

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] = '\0';
    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;
}

 

posted on 2016-11-05 20:39  stupid_one  阅读(233)  评论(0编辑  收藏  举报

导航