二分 + trie树大常数水过.
其实是一道字符串hash.
#include <cstdio>
#include <stack>
#include <cstring>
#include <cassert>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 5e2 + 20;
int N, M;
char str[MAXN << 1][MAXN];
inline int getnum(char ch){
switch (ch){
case 'A': return 0;
case 'T': return 1;
case 'C': return 2;
case 'G': return 3;
}
}
namespace trie
{
struct Node
{
bool ended;
Node *ch[4];
Node() : ended(false) {}
}pool[MAXN * MAXN], *pit = pool, root, null;
int cnt = 1;
inline Node *newnode(){
if(cnt < (MAXN * MAXN)) return ++cnt, new(pit++) Node();
return new Node();
}
Node *insert(Node *cur, char s[], int p){
if(!cur) cur = newnode();
if(!p) return cur->ended = true, cur;
cur->ch[getnum(*s)] = insert(cur->ch[getnum(*s)], s + 1, p - 1);
return cur;
}
bool query(Node *cur, char s[], int p){
if(!cur) return false;
if(!p) return cur->ended;
return query(cur->ch[getnum(*s)], s + 1, p - 1);
}
void init(){
for(int i = 0; i < 4; i++) null.ch[i] = NULL;
null.ended = false;
for(int i = 0; i < cnt; i++) pool[i] = null;
pit = pool, cnt = 1; root = null;
}
}
bool check(int x){
using namespace trie;
for(int l = 1; l <= (M - x + 1); l++){
init();
for(int i = 1; i <= N; i++) insert(&root, str[i] + l, x);
bool flag = false;
for(int i = N + 1; i <= (N << 1); i++)
if(query(&root, str[i] + l, x)) {
flag = true; break;
}
if(!flag) return true;
}
return false;
}
int main()
{
//freopen("p3667.in", "r", stdin);
cin>>N>>M;
for(int i = 1; i <= (N << 1); i++) scanf(" %s", str[i] + 1);
int l = 0, r = M;
while(l < r){
int mid = (l + r) >> 1;
if(check(mid)) r = mid;
else l = mid + 1;
}
cout<<l<<endl;
return 0;
}