POJ3007 Organize Your Train part II

Hash表来做,key值,链地址法。key公式等于字符串中所有字符asc2码乘对应位数的和


需要的函数
1.将s拆分为s1,s2
2.反转字符串
3.俩字符串合并
4.计算k值
5.建立并生成hash表函数
如果当前hash[key]不存在,则新建立,count++
如果当前存在
新hash对象指向该hash[key],检验是否相同,如果相同的结束函数,否则存在下一个时,新hash对象指向下一个hash,重复该步骤
直到所有该Key对应的hash[key]保存的字符都与当前字符串不同,则新建hash记录,count++


数据类型
哈希表类
存储:字符串
离散域:99991
key计算:所有当前字符(对应asc码)*字符所在的位数的和
链表:下一个同key哈希表

PS::注意实例化
Hashtable* Hash[MAXN];
void hashit(char* s)
{
    char* ps=s;
    int key=compute_k(ps);
    if(!Hash[key])
    {
        Hash[key]=new Hashtable;
        strcpy(Hash[key]->dic,s);
        count++;
    }
之前的写法肯定不行的
Hashtable* Hash[MAXN];
void hashit(char* s)
{
    char* ps=s;
    int key=compute_k(ps);
    if(!Hash[key])
    {
        strcpy(Hash[key]->dic,s);
        count++;
    }


因为Hash是指针集嘛,一开始都是空集,对应的实例也不存在,要先new一下的




WA点::如果题目有多组数据,在每个case之前,一定要先清零所有的变量和数据结构包括自定的复杂数据结构如哈希表等

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <cstdlib>
#include <math.h>
using namespace std;
const int MAXN=99991;
int count=0;
void StrInvert(char* s,char* s1,char* s2,int k)//k>=1&&k<=strlen(s)-1
{
    int t=k;
    for(int i=0;i<k;i++)
        s1[i]=s[i];
    for(int i=0;s[t];i++)
        s2[i]=s[t++];
    s1[k]='\0';
    s2[strlen(s)-k]='\0';
}
void StrConvert(char* s,char* s1)//反转
{
    char tmp[1010];
    int len=strlen(s);
    for(int i=len-1;i>=0;i--)
    {
        tmp[i]=*s++;
    }
    tmp[len]='\0';
    strcpy(s1,tmp);
}
void StrAdd(char*s1,char*s2,char* str)
{
    char tmp[1010];
    int len=strlen(s1);
    int t=0;
    for(int i=0;i<len;i++)
    {
        tmp[i]=*s1++;
    }
    for(int i=len;s2[t];i++)
    {
        tmp[i]=s2[t++];
    }
    tmp[len+strlen(s2)]='\0';
    strcpy(str,tmp);
}
int compute_k(char* s)
{
    int key=0;
    for(int i=1;i<=strlen(s);i++)
        key+=s[i-1]*i;
    return key%MAXN;
}
class Hashtable
{
public:
    char dic[1010];
    Hashtable* next;
    Hashtable()
    {
        next=0;
    }
};
Hashtable* Hash[MAXN];
void hashit(char* s)
{
    char* ps=s;
    int key=compute_k(ps);
    if(!Hash[key])
    {
        Hash[key]=new Hashtable;
        strcpy(Hash[key]->dic,s);
        count++;
    }
    else
    {
        Hashtable* pn=Hash[key];
        if(strcmp(pn->dic,s)==0)
            return;
        else
        {
            while(pn->next)
            {
                if(strcmp(pn->next->dic,s)==0)
                    return;
                else
                {
                    pn=pn->next;
                }
            }
            pn->next=new Hashtable;
            strcpy(pn->next->dic,s);
            count++;
            return;
        }
    }
}
int main()
{
    int n;
    cin>>n;
    while(n--)
    {
        count=0;
        char s[1010],str[1010];
        char s1[505],s2[505];
        char s3[505],s4[505];
        memset(Hash,0,sizeof(Hash));
        cin>>s;
        for(int k=1;k<strlen(s);k++)
        {
            StrInvert(s,s1,s2,k);
            StrConvert(s1,s3);
            StrConvert(s2,s4);
            StrAdd(s1,s2,str);
            hashit(str);
            StrAdd(s1,s4,str);
            hashit(str);
            StrAdd(s2,s1,str);
            hashit(str);
            StrAdd(s2,s3,str);
            hashit(str);
            StrAdd(s3,s2,str);
            hashit(str);
            StrAdd(s3,s4,str);
            hashit(str);
            StrAdd(s4,s1,str);
            hashit(str);
            StrAdd(s4,s3,str);
            hashit(str);
        }
        cout<<count<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值