两道题类似,uva455是求最小周期,hdu3746是求最少插入多少字符可以使得字符串最少有两个周期。
类似于kmp算法,使用一个next数组, 对字符串进行处理,标记所有的前缀, 时间复杂度是O(n)。
如:
字符串: a b c a b c d a b e f
next数组: 0 0 0 1 2 3 0 1 2 0 0
然后通过next数组来判断周期。
uva455 Periodic Strings:
#include <iostream> #include <cstring> using namespace std; void get_next(char P[], int next[], int m) { next[0] = 0; for (int i = 1, k = 0; i < m; ++i) { while (k > 0 && P[i] != P[k]) k = next[k - 1]; if (P[i] == P[k]) ++k; next[i] = k; } } int main() { int T, next[105]; char s[105]; cin >> T; while (T--) { cin >> s; int len = strlen(s); get_next(s, next, len); int ans, k = len - next[len - 1]; if (len % k == 0) ans = k; else ans = len; cout << ans << endl; if (T) cout << endl; } return 0; } hdu3746 Cyclic Nacklace:
#include <iostream> #include <cstdio> #include <cstring> using namespace std; void get_next(char P[], int next[], int n) //求next数组 { next[0] = 0; for (int i = 1, k = 0; i < n; ++i) { while (k > 0 && P[i] != P[k]) k = next[k - 1]; if (P[i] == P[k]) ++k; next[i] = k; } } int main() { int T, next[100005]; char s[100005]; scanf("%d", &T); while (T--) { scanf("%s", s); int n = strlen(s); get_next(s, next, n); int ans, k = n - next[n - 1]; if (k == n) // k==n时, next[n - 1]为0,所以需要插入n个字符 ans = n; else if (n % k == 0) //此时,字符串中已经至少两个周期 ans = 0; else ans = k - n % k; printf("%d\n", ans); } return 0; }
