超级传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4333
本题需要注意一点,需要统计的只是不重复的数字,所以先要用KMP求出串的循环节,然后只取一个周期进行匹配就行。用扩展KMP进行匹配,母串为输入串的两倍扩展(便于表示循环位移),在匹配的过程中判断大小。
代码如下:
#include <cstdio> #include <cstring> using namespace std; typedef struct __ans { int L, E, G; } Ans; char A[200020]; char B[100010]; int P[100010]; void preprocess(char* B, int* P, int m = -1) { P[0] = -1; int j = -1; if (m == -1) m = strlen(B); for (int i = 1; i < m; i++) { while (j != -1 && B[j + 1] != B[i]) j = P[j]; if (B[j + 1] == B[i]) j++; P[i] = j; } } Ans ex_kmp(char* A, char* B, int* P, int n = -1, int m = -1) { Ans ret = {0, 1, 0}; int a = 0, p, L; if (n == -1) n = strlen(A); if (m == -1) m = strlen(B); P[0] = m; while (a < m - 1 && B[a] == A[a + 1]) a++; P[1] = a; a = 1; for (int k = 1; k < m; k++) { p = a + P[a] - 1; L = P[k - a]; if ((k - 1) + L >= p) { int j = (p - k + 1) > 0 ? (p - k + 1) : 0; while (k + j < n && A[k + j] == B[j]) j++; P[k] = j; a = k; } else P[k] = L; if (P[k] == m) ret.E++; else if (P[k] < m) { if (A[k + P[k]] < B[P[k]]) ret.L++; if (A[k + P[k]] > B[P[k]]) ret.G++; } } return ret; } int main() { int t; scanf("%d", &t); for (int i = 1; i <= t; i++) { scanf("%s", B); int m = strlen(B); preprocess(B, P, m); if (m % (m - P[m - 1] - 1) == 0) m = m - P[m - 1] - 1; memcpy(A, B, sizeof(char) * m); memcpy(A + m, B, sizeof(char) * m); A[m << 1] = '\0'; Ans ans = ex_kmp(A, B, P, m << 1, m); printf("Case %d: %d %d %d\n", i, ans.L, ans.E, ans.G); } return 0; }
作者:michaelalan 发表于2013-3-4 22:39:33 原文链接
阅读:59 评论:0 查看评论