POJ 3007(字符串hash)

本文针对POJ3007题目的解决方法进行了深入探讨,使用字符串Hash算法来解决字符串匹配问题,避免了传统方法中的超时问题,并通过set与Hash结合的方法实现了高效的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

POJ 3007

题目大意

这里写图片描述

分析

一开始用map做超时,后面看网上题解用字符串hash,然而这道题却被分到的是STL类的题。后面看到一篇用set+hash做了,用了这个方法后900+ms险过。

然而还是感觉这个方法有点投机取巧,里面是直接把字符串求出一个取模后(模比较大)的key后放到set里

像这种不加冲突处理的hash也能过set没有超时只能说是运气好了

后面有空再写写标准的字符串hash

一篇不错的hash讲解:字符串 hash算法

​hash表常用的两种地址冲突方法是开放地址法和拉链法

代码

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<map>
#include<algorithm>
#include<set>
using namespace std;
const int INF=999999999;
typedef long long int LL;
const LL MOD=100000000007;
char  s[100];
char s1[100],s2[100];
char r1[100],r2[100];
int ans=0;
set<LL> Set;
void Insert(char  s1[],char s2[],int len1,int len2)
{
     LL key=0;
     for(int i=0;i<len1;i++)
         key=(key*29+(int)s1[i]-(int)'a'+1)%MOD;
     for(int i=0;i<len2;i++)
         key=(key*29+(int)s2[i]-(int)'a'+1)%MOD;
     //cout<<t<<" "<<key<<endl;
     if(Set.count(key)==0){Set.insert(key);ans++;}

}
void Substr(char s[],char s2[],int a,int b)//Substr(s,s2,i,j)函数将字符串s下标a到b-1部分子串保存到s2中
{
     for(int i=a;i<b;i++)
           s2[i-a]=s[i];
     s2[b]='\0';
}
void Reverse(char s[],char r[],int len)
{
      for(int i=0;i<len;i++)
      {
            r[i]=s[len-i-1];
      }
}
void Work()
{
      int len=strlen(s);
      int len1,len2;
      for(int i=0;i<=len-2;i++)
      {
           Substr(s,s1,0,i+1);
           Substr(s,s2,i+1,len);
           len1=i+1;
           len2=len-i-1;
           Reverse(s1,r1,len1);//将s1反转后的结果放到r1中
           Reverse(s2,r2,len2);
           Insert(s1,s2,len1,len2);
           Insert(s1,r2,len1,len2);
           Insert(r1,s2,len1,len2);
           Insert(r1,r2,len1,len2);

           Insert(s2,s1,len2,len1);
           Insert(s2,r1,len2,len1);
           Insert(r2,s1,len2,len1);
           Insert(r2,r1,len2,len1);
      }
      cout<<ans<<endl;
      Set.erase(Set.begin(),Set.end());
      ans=0;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
          scanf("%s",s);
          Work();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值