poj 3080 后缀树应用

学习了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;
}  



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值