题意:给N个文本串 找到在一个在N个文本串中都出现的最长的字典序最小的字串
本来找的是KMP 的题 想来半天都不知道怎么用KMP搞
之后发现可以 将每个串的后缀都加入一颗字典树中
字典树中每个节点的value表示一个状态 即 这个串在哪几个序列中出现过
最后在树上深搜 按A C G T 的顺序搜索
最后在逆这树向上打印文本
时间复杂度: 一个串有len个后缀 将一个长度为n的串加入字典树要用O(n) 所以插入一个长为len的串的时间为 O(len ^ 2) 有N个串 O(N * Len ^ 2)
说一下静态字典树的长度预测 串数上限为N 串长上限为M 假设每次插入的都是新节点 则需要N * M个节点
代码:
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <ctime>
#define sf scanf
#define pf printf
using namespace std;
const int sigma_size = 4;
const int maxn = 40000;
int ch[maxn][sigma_size];
int node_cnt;
int value[maxn];
int pre[maxn];
char pf_ans[] = {'A','C','G','T'};
int IDX(char c){
if(c == 'A') return 0;
else if(c == 'C') return 1;
else if(c == 'G') return 2;
else return 3;
}
void init_trie(){
node_cnt = 1;
memset(ch[0],0,sizeof(ch[0]));
pre[0] = -1;
}
bool ok(char* s,int len){
char temp[] = "CATCATCAT";
for(int i = 0;i <= len;++i){
if(temp[i] != s[i]) return false;
}
return true;
}
void Insert(char *s,int v){
// puts(s);
int len = strlen(s);
int cur = 0,idx;
for(int i = 0;i < len;++i){
idx = IDX(s[i]);
if(ch[cur][idx] == 0){
ch[cur][idx] = node_cnt;
memset(ch[node_cnt],0,sizeof(ch[node_cnt]));
value[node_cnt] = 0;
pre[node_cnt++] = cur;
}
cur = ch[cur][idx];
value[cur] = value[cur] | v;
// if(ok(s,i)) pf("%d\n",value[cur]);
}
}
int ans_deep,ans_lable,ans_state;
//char check[70];
void DFS(int cur,int deep){
// pf("%d\n",cur);
if(value[cur] == ans_state && ans_deep < deep){
ans_deep = deep;
ans_lable = cur;
// check[deep] = '\0';
// puts(check);
}
for(int i = 0;i < sigma_size;++i){
if(ch[cur][i]){
// check[deep] = pf_ans[i];
DFS(ch[cur][i],deep + 1);
}
}
}
void PRINT_ANS(int cur,int PRE){
if(cur == -1) return;
else{
PRINT_ANS(pre[cur],cur);
for(int i = 0;i < sigma_size;++i){
if(ch[cur][i] == PRE) {pf("%c",pf_ans[i]);break;}
}
}
}
char str[100];
int main(){
// freopen("read.txt","r",stdin);
int T,n;
sf("%d",&T);
while( T-- ){
init_trie();
sf("%d",&n);
ans_state = (1 << n) - 1;
for(int i = 0;i < n;++i){
sf("%s",str);
char* insert_str = str;
while(*insert_str){
Insert(insert_str,1 << i);
insert_str++;
}
}
ans_deep = 0;
DFS(0,0);
if(ans_deep < 3){
pf("no significant commonalities");
}
else PRINT_ANS(ans_lable,-1);
pf("\n");
}
return 0;
}