re-implement the kmp