题目大意
分析
一开始用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();
}
}