D. Match & Catch
可以用各種方法做,字符串hash,後綴數組,dp,拓展kmp,字典樹。。。
字符串hash(模板)
http://blog.csdn.net/gdujian0119/article/details/6777239
BKDR Hash Function :
// BKDR Hash Function unsigned int BKDRHash(char *str) { unsigned int seed = 131; // 31 131 1313 13131 131313 etc.. unsigned int hash = 0; while (*str) { hash = hash * seed + (*str++); } return (hash & 0x7FFFFFFF); }
#define ULL unsigned long long const int maxn = 5111 * 2; const int HASH = 10007; struct HashMap{ int head[HASH]; int next[maxn]; ULL state[maxn]; int num_s1[maxn]; int num_s2[maxn]; int sz; void init() { sz = 0; memset(head, -1, sizeof(head)); } int insert(ULL val, bool info) { int h = val % HASH; for (int i = head[h]; i != -1; i = next[i]) { if (val == state[i]) { if (info) num_s1[i]++; else num_s2[i]++; return 1;///存在 } } num_s1[sz] = 0; num_s2[sz] = 0; state[sz] = val; next[sz] = head[h]; if (info) num_s1[sz]++; else num_s2[sz]++; head[h] = sz++; return 0;///不存在 } bool check() { for (int i = 0; i < sz; i++) { if (num_s1[i] == num_s2[i] && num_s1[i] == 1) return true; } return false; } }H; const int SEED = 13331; ULL P[maxn]; ULL s1[maxn], s2[maxn]; char sa[maxn], sb[maxn]; void hash_pre(ULL P[]) { P[0] = 1; for (int i = 1; i <= maxn; i++) P[i] = P[i - 1] * SEED; } void hash_init(ULL s1[], char sa[])///sa[],下標從0開始;對應是s1[]的值得下標從1開始 { int n = strlen(sa); s1[0] = 0; for (int i = 1; i <= n; i++) s1[i] = s1[i - 1] * SEED + sa[i - 1]; } ULL getSeg(ULL s1[], int l, int r)///求s1[]的下標區間的hash值 { return s1[r] - s1[l - 1] * P[r - l + 1]; } int main() { hash_pre(P); RS(sa); RS(sb); int n = strlen(sa), m = strlen(sb); hash_init(s1, sa); hash_init(s2, sb); int fla = 0; int mn = min(n, m); for (int i = 1; i <= mn; i++) { H.init(); for (int j = i; j <= n; j++) { H.insert(getSeg(s1, j - i + 1, j), 0); } for (int j = i; j <= m; j++) { H.insert(getSeg(s2, j - i + 1, j), 1); } if (H.check()) { printf("%d\n", i); fla = 1; break; } } if (!fla) puts("-1"); return 0; }
後綴數組:
const int MAXN = 5111 * 2; const int INF = 0x3f3f3f3f; int wa[MAXN], wb[MAXN], wv[MAXN], wn[MAXN]; //char r[MAXN]; int a[MAXN], sa[MAXN], rank[MAXN], height[MAXN]; int cmp(int *r, int a,int b, int k) { return r[a] == r[b] && r[a + k] == r[b + k]; } void build_sa(int *r, int *sa, int n,int m) { int i,j, p; int *x = wa, *y = wb, *t; for (int i= 0; i < m; i++) wn[i] = 0; for (int i= 0; i < n; i++) wn[x[i] = r[i]]++; for (int i = 1; i < m; i++) wn[i] += wn[i - 1]; for (int i = n - 1; i >= 0; i--) sa[--wn[x[i]]] = i; for (p = 1, j = 1; p < n; j <<= 1, m = p) { for (p = 0, i = n - j; i < n; i++) y[p++] = i; for (i = 0; i < n; i++) if (sa[i] >= j) y[p++] = sa[i] - j; for (i = 0; i < m; i++) wn[i] = 0; for (i = 0; i < n; i++) wn[wv[i] = x[y[i]]]++; for (i = 1; i < m; i++) wn[i] += wn[i - 1]; for (i = n - 1; i >= 0; i--) sa[--wn[wv[i]]] = y[i]; t = x; x = y; y = t; x[sa[0]] = 0; p = 1; for (i = 1; i < n; i++) x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++; } } void getHeight(int *r, int *sa, int n) { int i, j, k = 0; for (i = 1; i <= n; i++) { rank[sa[i]] = i; height[i] = 0; } for (i = 0;i < n; i++) { if (k) k--; j = sa[rank[i] - 1]; while (r[i + k] == r[j + k]) k++; height[rank[i]] = k; } } char ca[MAXN], cb[MAXN]; void solve(int n) { height[n + 1] = 0; int ans = INF; int l = strlen(ca); for (int i = 1; i <= n; i++) { if (!height[i]) continue; if (sa[i] < l && sa[i - 1] < l) continue; if (sa[i] >= l && sa[i - 1] >= l) continue; int pre = height[i - 1] + 1; int next = height[i + 1] + 1; if (height[i] >= max(pre, next)) { ans = min(ans, max(pre, next)); } } if (ans == INF) puts("-1"); else printf("%d\n", ans); } int main() { int t, n, m; ///n, m n = 0; m = 256; RS(ca); int l = strlen(ca); REP(j, l) a[n++] = (int)ca[j]; a[n++] = m++; RS(cb); l = strlen(cb); REP(j, l) a[n++] = (int)cb[j]; a[n++] = m++; a[--n] = 0; --m; build_sa(a, sa, n + 1, m); getHeight(a, sa, n); solve(n); return 0; } /* 0 8 0 1 6 0 2 4 2 3 2 4 4 0 6 5 7 0 6 5 1 7 3 3 8 1 5 ^^^^^^^^^^^^^^ 0 4 1 8 2 3 3 7 4 2 5 6 6 1 7 5 8 0 ^^^^^^^^^^^^^^ */