#include #include #include #define MAXK 64 #define ALFA 26 #define HASH 102400 static size_t cbuf[MAXK][ALFA]; struct ht { size_t hash; unsigned char val[ALFA]; struct ht *next; struct ht *alloc_next; }; struct hte { struct ht *list; unsigned gen; }; static struct hte table[HASH]; static unsigned gen; static struct ht *alloc_list, *alloc_head, **alloc_tail = &alloc_head; static size_t hash_fn (const unsigned char vals[ALFA]) { size_t val, i; val = 0; for (i = 0; i < ALFA; i++) val = (val >> 31) ^ (val << 1) ^ vals[i]; return val; } static void hash_clear (void) { alloc_list = alloc_head; gen++; } static int hash_add (const unsigned char diff[ALFA]) { struct ht *ht; struct hte *hte; size_t hash; hash = hash_fn (diff); hte = table + hash % HASH; if (hte->gen == gen) { for (ht = hte->list; ht != NULL; ht = ht->next) { if (ht->hash == hash && memcmp (ht->val, diff, sizeof (ht->val)) == 0) return 1; } } if (alloc_list == NULL) { alloc_list = malloc (sizeof (*alloc_list)); alloc_list->alloc_next = NULL; *alloc_tail = alloc_list; alloc_tail = &alloc_list->alloc_next; } ht = alloc_list; alloc_list = alloc_list->next; ht->hash = hash; memcpy (ht->val, diff, sizeof (ht->val)); if (hte->gen != gen) { hte->gen = gen; hte->list = NULL; } ht->next = hte->list; hte->list = ht; return 0; } int main (void) { for (;;) { static char orig[102400], clean[102400]; char *p, *q; unsigned k; size_t i; scanf("%u ", &k); if (k == 0) break; hash_clear (); gets(orig); q = clean; for (p = orig; *p != 0; p++) { if (*p >= 'a' && *p <= 'z') *q++ = *p; else if (*p >= 'A' && *p <= 'Z') *q++ = *p - ('A' - 'a'); } *q = 0; for (i = 0; i < ALFA; i++) cbuf[0][i] = 0; for (i = 0; clean[i] != 0; i++) { size_t old, new; old = i % MAXK; new = (i + 1) % MAXK; memcpy (cbuf[new], cbuf[old], sizeof (cbuf[new])); cbuf[new][clean[i] - 'a']++; if (i + 1 >= k) { unsigned char diff[ALFA], j; old = i + 1 - k; for (j = 0; j < ALFA; j++) diff[j] = cbuf[new][j] - cbuf[old][j]; if (hash_add (diff) != 0) break; } } q = clean; for (p = orig; *p != 0; p++) { if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z')) { if (q == clean + i) break; q++; } } printf ("%u\n", p - orig); } return 0; }