学习了o(n)后缀树后的应用,数据量太少,47ms比暴搜慢,然而掌握比解题重要,要快去除内存处理更快,但养成坏习惯不值得。代码量大
#include<iostream>
#include<map>
#include <string>
#include<algorithm>
#include<fstream>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
#define lch(i) ((i)<<1)
#define rch(i) ((i)<<1|1)
#define sqr(i) ((i)*(i))
#define pii pair<int,int>
#define mp make_pair
#define FOR(i,b,e) for(int i=b;i<=e;i++)
#define FORE(i,b,e) for(int i=b;i>=e;i--)
#define ms(a) memset(a,0,sizeof(a))
const int maxnum =20007;
const int key = 177;
int n,m,len,deepest;
typedef struct node
{
int depth;
bool nth[10];
int len;
int pos;
char* str;
node* next;
node* father;
vector<node*> son;
typedef vector<node*>::iterator
soniterator;
node(): str(NULL),
len(0),
depth(0),
pos(-1),
next(NULL),
father(NULL),
son(){}
node(node const& a):str(a.str),
len(a.len),
pos(a.pos),
depth(a.depth),
next(a.next),
father(a.father),
son(a.son){}
~node(){}
}*pnode;
class suffixtree{
public:
node* ST,*LEND,*root;
int num;
char* strs[10];
suffixtree(){
root = new node;
root->depth=root->len=0;
root->next=root;
root->father=root;
root->pos=-1;
num=0;
}
void destroy(node* p){
int size = p->son.size();
FOR(i,0,size-1)
destroy(p->son[i]);
delete p;
}
void clear(){
destroy(root);
root = new node;
FOR(i,0,num-1){
delete[] strs[i];
}
root->depth=root->len=0;
root->next=root;
root->pos=-1;
num=0;
}
~suffixtree(){
destroy(root);
FOR(i,0,num-1){
delete[] strs[i];
}
}
void bfs(){
node* ptr;
queue<node*> que;
queue<int> deep;
que.push(root);
deep.push(0);
int nowdeep=0,tmpd;
while(!que.empty()){
ptr = que.front();
que.pop();
tmpd = deep.front();
deep.pop();
node::soniterator si = ptr->son.begin();
for(;si!=ptr->son.end();si++){
que.push(*si);
deep.push(tmpd+1);
}
if(tmpd>nowdeep){nowdeep++; printf("\n");}
if(ptr==root)continue;
FOR(i,0,ptr->len-1){
printf("%c",ptr->str[i]);
}
printf(" ");
}
}
node* matchstr(node *tmp,char si){
if(tmp->son.empty()) return 0;
int size = tmp->son.size();
FOR(i,0,size-1){
if(tmp->son[i]->str[0]==si){
return tmp->son[i];
}
}
return 0;
}
node* FindLastPos(node* p,int len,char *str){
node* tmpP = p;
while(tmpP->depth<len){
tmpP=matchstr(tmpP,str[tmpP->depth]);
}
if(tmpP->depth>len){
tmpP->pos=len-tmpP->father->depth;
}
return tmpP;
}
node* createLeaf(node *tmp,int pos,char *s);
node* splitnode(node *tmp,int pos,char *s);
void addstring(char *s);
};
node* suffixtree::createLeaf(node *tmp,int pos,char *s){
node *explicitnode =new node;
explicitnode->len=len-pos;
explicitnode->depth=tmp->depth+explicitnode->len;
explicitnode->father=tmp;
explicitnode->str = s;
explicitnode->next=root;
tmp->son.push_back(explicitnode);
return explicitnode;
}
node* suffixtree::splitnode(node *tmp,int pos,char *s){
node *explicitnode = new node;
explicitnode->str=tmp->str;
explicitnode->len=tmp->pos;
explicitnode->depth=tmp->father->depth+explicitnode->len;
explicitnode->father=tmp->father;
explicitnode->son.push_back(tmp);
explicitnode->next=root;
int si = tmp->father->son.size();
FOR(i,0,si-1){
if(tmp->father->son[i]->str[0]==tmp->str[0]){
tmp->father->son[i]=explicitnode;
break;
}
}
tmp->len-=explicitnode->len;
tmp->str+=explicitnode->len;
tmp->father=explicitnode;
tmp->pos=-1;
createLeaf(explicitnode,pos,s);
return explicitnode;
}
void suffixtree::addstring(char *s){
len = strlen(s);
strs[num]=new char[len+2];
strcpy(strs[num],s);
strs[num][len]=num+'0';
strs[num][len+1]='\0';
char *str = strs[num];
num++;
LEND= root;
int st_=0;
len++;
node *p=root,*tmp,*matchson;
ST=0;
FOR(i,0,len-1){
LEND=root;
FOR(j,st_,i){
tmp = FindLastPos(p,i-j,str+j);
if(tmp->pos==-1){
if(LEND!=root)
LEND->next=tmp;
LEND=tmp;
matchson = matchstr(tmp,str[i]);
if(matchson!=0){
p=tmp;
break;
}else{
createLeaf(tmp,i,str+i);
st_++;
p=tmp;
}
}else{
if(tmp->str[tmp->pos]==str[i]){
tmp->pos=-1;
break;
}
else{
tmp=splitnode(tmp,i,str+i);
if(LEND!=0&&LEND!=root)
LEND->next=tmp;
LEND=tmp;
p=tmp->father;
st_++;
}
}
p=p->next;
}
}
str=0;
}
node* dnode;
bool dfs(node* now){
int si = now->son.size();
ms(now->nth);
if(si==0){
now->nth[now->str[now->len-1]-'0']=1;
return false;
}
bool flag=0;
FOR(i,0,si-1){
if(dfs(now->son[i])){
flag=1;
}
FOR(j,0,m-1)
now->nth[j]|=now->son[i]->nth[j];
}
if(!flag){
int sum=0;
FOR(j,0,m-1)
sum+=now->nth[j];
if(sum==m){
flag=1;
}
}
if(flag){
if(deepest<now->depth){
deepest=now->depth;
dnode = now;
}
if(deepest==now->depth&&deepest!=0){
char* newn = now->str+now->len-deepest;
char* orin = dnode->str+dnode->len-deepest;
FOR(i,0,deepest-1){
if(newn[i]==orin[i])continue;
if(newn[i]-orin[i]<0){
dnode=now;
break;
}else{
break;
}
}
}
return true;
}
return false;
}
int main()
{
/*fstream fin("G:/1.txt");*/
suffixtree stree;
/*fin>>n;*/
scanf("%d",&n);
char base[61];
while(n--){
stree.clear();
/*fin>>m;*/
scanf("%d",&m);
FOR(i,1,m){
/*fin>>base;*/
scanf("%s",base);
stree.addstring(base);
}
deepest=0;
dnode=0;
dfs(stree.root);
if(deepest>2){
char* orin = dnode->str+dnode->len-deepest;
FOR(i,0,deepest-1)
printf("%c",orin[i]);
printf("\n");
}
else
printf("no significant commonalities\n");
}
return 0;
}