字符串hash判重/trie树判重(poj3007)

此题还可以trie树判重

利用了c++ stl的优势

1.s.erase(s.begin(),s.end());//set全部清空的方式

2. memset(b2,0,sizeof(b2));//char数组全部清空 ,中间0表示ascall码

hash判重,set存

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<set>
#define debug(x) cout<<#x<<"="<<x<<endl
using namespace std;
typedef long long ll;
const int mod=1e9+7;
char a[105],b1[105],b2[105],t[10];
int len,ans;
set<ll> s;
void pan(char *b1,char *b2)
{
	ll key=0;
	int len1=strlen(b1),len2=strlen(b2);
	for (int i=0;i<len1;i++) key=(key*29+(b1[i]-'a'+1))%mod;
	for (int i=0;i<len2;i++) key=(key*29+(b2[i]-'a'+1))%mod;//字符串hash
	if (s.count(key)==0) ans++,s.insert(key);//set判断是否已经出现
}
void rev(char *a)
{
	int len=strlen(a);
	char b;
	for (int i=0;i<len/2;i++)//注意这里旋转,是要转前半部分,后部分如果再转就转回来了
	{
		b=a[i];a[i]=a[len-i-1];a[len-i-1]=b;
	}
}
void work()
{
	s.erase(s.begin(),s.end());//set的清空方式 
	ans=0;
	scanf("%s",a);
	len=strlen(a);
	pan(t,a);
	for (int i=1;i<len;i++)
	{
		memset(b1,0,sizeof(b1));
		memset(b2,0,sizeof(b2));//char数组清空 
		for (int j=0;j<i;j++) b1[j]=a[j];
		for (int j=i;j<len;j++) b2[j-i]=a[j];
		rev(b2);pan(b1,b2);
		rev(b1);pan(b1,b2);
		rev(b2);pan(b1,b2);
		rev(b1);
				pan(b2,b1);
		rev(b1);pan(b2,b1);
		rev(b2);pan(b2,b1);
		rev(b1);pan(b2,b1);
	}
	printf("%d\n",ans);
}
int main()
{
	int T;
	scanf("%d",&T);
	while (T--) work();
	return 0;
}

Trie树判重,注意trie树清空的问题,memset费时,

trie树判重可以通过他的特性做一些方便的用途

such as:给你100000个长度不超过10的单词。对于每一个单词,我们要判断他出没出现过,如果出现了,第一次出现第几个位置。
这题当然可以用hash来,但是我要介绍的是trie树。在某些方面它的用途更大。比如说对于某一个单词,我要询问它的前缀是否出现过。这样hash就不好搞了,而用trie还是很简单。

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<set>
#define debug(x) cout<<#x<<"="<<x<<endl
using namespace std;
char a[105],b1[105],b2[105],t[10];
int len,ans,ch[400009][27],tot,val[400009];
inline int idx(char a)
{
	return a-'a';
}
void pan(char *b1,char *b2)//trie树判重
{
	int k=0,len1=strlen(b1),len2=strlen(b2);
	for (int i=0;i<len1;i++)
	{
		int x=idx(b1[i]);
		if (ch[k][x]) k=ch[k][x];
		else 
		{
			k=ch[k][x]=++tot;
			memset(ch[k],0,sizeof(ch[k]));	
		}
	}
	for (int i=0;i<len2;i++)
	{
		int x=idx(b2[i]);
		if (ch[k][x]) k=ch[k][x];
		else 
		{
			k=ch[k][x]=++tot;
			memset(ch[k],0,sizeof(ch[k]));
		}
	}
	if (val[k]) return;
	val[k]=1;ans++;
}
void rev(char *a)
{
	int len=strlen(a);
	char b;
	for (int i=0;i<len/2;i++)
	{
		b=a[i];a[i]=a[len-i-1];a[len-i-1]=b;
	}
}
void work()
{
	ans=tot=0;
	memset(ch[0],0,sizeof(ch[0]));
	memset(val,0,sizeof(val));
	scanf("%s",a);
	len=strlen(a);
	pan(t,a);
	for (int i=1;i<len;i++)
	{
		memset(b1,0,sizeof(b1));
		memset(b2,0,sizeof(b2));//char数组清空 
		for (int j=0;j<i;j++) b1[j]=a[j];
		for (int j=i;j<len;j++) b2[j-i]=a[j];
		rev(b2);pan(b1,b2);
		rev(b1);pan(b1,b2);
		rev(b2);pan(b1,b2);
		rev(b1);
				pan(b2,b1);
		rev(b1);pan(b2,b1);
		rev(b2);pan(b2,b1);
		rev(b1);pan(b2,b1);
	}
	printf("%d\n",ans);
}
int main()
{
	int T;
	scanf("%d",&T);
	while (T--) work();
	return 0;
}
    原文作者:Trie树
    原文地址: https://blog.csdn.net/zhhx2001/article/details/51979725
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注