题目链接:http://poj.org/problem?id=3007
题意:给出一个字符串,从任意一个地方切开,分成两个字符串s1,s2,然后分别反转成s3,s4,然后将四个字符串任意组合(子串及其反串不可组合),求出所有不同的组合数。
如果用STL的话这题会超时,map什么的都用不了,就自己写了一个丑陋的哈希,设计的哈希函数也比较简单,47ms才过。
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const int H=10007;
const int maxn=10010;
int hashTable[maxn],cnt;
int T;
char s[80],s1[80],s2[80],s3[80],s4[80],str[200];;
struct node{
char str[maxn];
int next;
}p[maxn];
void initHash();
int getHash(char *s);
void addHash(char *s,int hashNum);
bool searchHash(char *s);
void strCut(char *s,char *s1,char *s2,int index);
void strReverse(char *s1,char *s2);
void strCat(char *s1,char *s2,char *str);
int main(){
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
#endif
scanf("%d",&T);
while(T--){
initHash();
scanf("%s",s);
if(!searchHash(s)) cnt++;
int len=strlen(s);
for(int i=1;i<=len-1;i++){
strCut(s,s1,s2,i);
strReverse(s1,s3);
strReverse(s2,s4);
strCat(s1,s4,str);
if(!searchHash(str)) cnt++;
strCat(s3,s2,str);
if(!searchHash(str)) cnt++;
strCat(s3,s4,str);
if(!searchHash(str)) cnt++;
strCat(s2,s1,str);
if(!searchHash(str)) cnt++;
strCat(s2,s3,str);
if(!searchHash(str)) cnt++;
strCat(s4,s1,str);
if(!searchHash(str)) cnt++;
strCat(s4,s3,str);
if(!searchHash(str)) cnt++;
}
printf("%d\n",cnt);
}
return 0;
}
int getHash(char *s){
int hash=0,len=strlen(s);
for(int i=0;i<len;i++)
hash=hash+s[i]*(i+1);
return hash%H;
}
void initHash(){
cnt=0;
memset(hashTable,-1,sizeof(hashTable));
}
void addHash(char *s,int hashNum){
int len=strlen(s);
for(int i=0;i<len;i++)
p[cnt].str[i]=s[i];
p[cnt].str[len]='\0';
p[cnt].next=hashTable[hashNum];
hashTable[hashNum]=cnt;
}
bool searchHash(char *s){
int hashNum=getHash(s);
int next=hashTable[hashNum];
for(int i=next;i!=-1;i=p[i].next){
if(!strcmp(s,p[i].str))
return true;
}
addHash(s,hashNum);
return false;
}
void strCut(char *s,char *s1,char *s2,int index){
int len=strlen(s);
for(int i=0;i<index;i++)
s1[i]=s[i];
s1[index]='\0';
for(int i=index;i<len;i++)
s2[i-index]=s[i];
s2[len-index]='\0';
}
void strReverse(char *s1,char *s2){
int len=strlen(s1);
for(int i=0;i<len;i++)
s2[i]=s1[len-1-i];
s2[len]='\0';
}
void strCat(char *s1,char *s2,char *str){
int len1=strlen(s1);
int len2=strlen(s2);
int index=0;
for(int i=0;i<len1;i++)
str[index++]=s1[i];
for(int j=0;j<len2;j++)
str[index++]=s2[j];
str[index]='\0';
}