Anagram Groups POJ - 2408(字典树)

世界著名的A.N.Agram教授目前的研究涉及大型变位词组。他刚刚发现了一个新的应用,为他的理论在英语文本中的字符分布。给定这样的文本,您将找到最大的变位词组。              

文本是一系列单词。一个单词w是一个单词v的变位词,如果且仅当字符位置的某些排列p带w到v时。那么,w和v在同一个变位词组中。变位词组的大小是该组中的单词数。找到5个最大的变位词组。            

 输入              

输入包含由小写字母字符组成的单词,用空格(或新行)分隔。它由EOF终止。你可以假设不会超过30000个单词。              

输出              

输出5个最大的变位词组。如果少于5组,则全部输出。按减小的大小对组进行排序。用词典编纂的最小元素在词典编纂上打破联系。对于每个组输出,打印其大小和成员字。按字典顺序对成员词排序,并只打印一次相同的词。

Sample Input

undisplayed
trace
tea
singleton
eta
eat
displayed
crate
cater
carte
caret
beta
beat
bate
ate
abet

Sample Output

Group of size 5: caret carte cater crate trace .
Group of size 4: abet bate beat beta .
Group of size 4: ate eat eta tea .
Group of size 1: displayed .
Group of size 1: singleton .

题意就是这样,从一堆字符串中找到 字符串可以交换位置就一样的同样的字符串,并将相同形式的字符串都放在一起(按原来字典序排序),一开始就直接 set数组,map 之间查找,直接超时。还是写字典树吧。

将每个单词最后的一个节点进行查询,如果没有被标记,就是一个新的单词,就将它放到一个新的结构体中的set 中,如果已经被标记就在原来的结构体中插入就可以了 ,字典树在某些方面还是很好用的,在字典树中就可以简单找到该单词的最终节点,再来一个计数器,将这个单词插入到制定下表的结构体中。

最后在遍历输出5个set集合,就可以了。

#include<iostream>
#include<cstdio>
#include<map>
#include<algorithm>
#include<set>
#include<string>
#include<string.h>


using namespace std;
#include<sstream> 

const int maxn=1e6+5;

int tree[maxn][30];
int tot;
int anstot;
int vis[maxn];
int num[30];
char s[maxn];

struct point 
{
	int num;
	set<string>mp;
	
}zifu[maxn];



bool cmp(const point &a ,const point &b )
{
	if(a.num==b.num)
    {
        return *(a.mp.begin()) < *(b.mp.begin());
    }
    return a.num>b.num;

		
	
}




void insert(char *s)
{
	int root=0;
	int len=strlen(s);
	string t=s;        //字典序的字符串 
	/*for(int i=0;i<len;i++)
		num[s[i]-'a']++;
	
	for(int i=0;i<26;i++)
	{
		while(num[i]!=0)
		{
			t+=(i+'a');
			num[i]--;
		}
	}*/
	sort(t.begin(),t.end());
	
	for(int i=0;i<len;i++)
	{
		int x=t[i]-'a';
		if(!tree[root][x])
			tree[root][x]=++tot;
		
		root=tree[root][x];
	}
	if(!vis[root])
		vis[root]=++anstot;
	
	zifu[vis[root]].num++;
	string tmp=s;
	zifu[vis[root]].mp.insert(tmp);
	
	return ;
}



int main()
{
	
	
	while(scanf("%s",s)!=EOF)
	{
		insert(s);
	}
	
	sort(zifu+1,zifu+1+anstot,cmp);
	
	
	for(int i=1;i<=5;i++)
	{
		printf("Group of size %d: ",zifu[i].num);
		set<string>::iterator it;
		
		for(it=zifu[i].mp.begin();it!=zifu[i].mp.end();++it)
			printf("%s ",(*it).c_str());
		printf(".\n");
		
	}
	
	
	return 0;
}

在每个单词在判断是否可以(进行排序可以成为一类单词),我们就直接用sort 库函数,直接将插入的串排序,然后再套字典树模板将最后节点标记了(并用计数器来计数)。如果单词已经存在,那么最后的 root 就会出现过,就直接插入到已存在的结构体中。 

get it;

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值