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] = '