字符串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
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞