您的位置:首页 > 其它

暑假- Trie树-(A - Shortest Prefixes)

2015-07-28 09:53 447 查看
/*
题意:找出能唯一标示一个字符串的最短前缀,如果找不出,就输出该字符串。 
思路:trie树,所谓唯一最短前缀,就是这个前缀的最后一个字母在之前所有输入的
字符串中只出现过一次(除了找不到的以外),构树的时候每个字母出现一次再所对应的
value++,最后判断这个串的哪个字母是首个出现了一次的字母,则从这个串开始到这个
首次出现了一次的字母结束就是对应的唯一前缀。
*/
#include<iostream>
#include<cstring>
#include<stdio.h>
using namespace std;
const int MAXN=1005;
const int MAXM=100005;
struct Node
{
	int value;//标记出现的次数
	int child[26];//孩子节点
	Node()
	{
		value=0;
		memset(child,0,sizeof(child));
	}
};
Node trie[MAXM];
int trieN=0;
void create(char s[])//构树
{
	int x=0;
	for(int i=0;i<strlen(s);i++)
	{
		int d=s[i]-'a';
		if(trie[x].child[d]==0)//不存在这个孩子节点
		{
			trie[++trieN]=Node();//则构建出一个孩子节点。
			trie[x].child[d]=trieN;//孩子节点的下标。
			x=trie[x].child[d];//转移节点。
			trie[x].value++;//出现次数+1
		}
		else//存在这个孩子节点
		{
			x=trie[x].child[d];//转移节点
			trie[x].value++;//出现次数+1
		}
	}
}
int Search(char s[])//寻找前缀
{
	int x=0;//出根节点开始
	int len=strlen(s);
	for(int i=0;i<len;i++)
	{
		int d=s[i]-'a';
		x=trie[x].child[d];//转换子树
		if(trie[x].value==1)//如果这个字母只出现一次,则返回这个
		{                   //字母所在的下标
			return i;
		}
	}
	return len-1;//否则,不存在唯一前缀,则按要求输出整个串,所以返回这个串的长度
}
int main()
{
	char s[MAXN][25];
	int t=0;
	while(scanf("%s",s[t])!=EOF)//输入数据,构树
	{
		create(s[t]);
		t++;
	}
	for(int i=0;i<t;i++)
	{
		cout<<s[i]<<' ';//输出原串
		int k=Search(s[i]);//寻找唯一前缀的最后一个字母的下标。
		for(int j=0;j<=k;j++)
		{
			cout<<s[i][j];
		}
		cout<<endl;
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: