//572K 407MS G++
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct HashMapNode {
int nextNodePos;
char content[80];
char occupied;
};
typedef struct HashMapNode HashMapNode;
const int MAP_SIZE = 2377;
class HashMap {
HashMapNode nodeArray[MAP_SIZE];
int hashMapBucket[MAP_SIZE];
int hash(const char * str, int hash_table_size = MAP_SIZE);
int stringNum;
int availableNodeArrayPos;
public:
HashMap() {
clear();
}
int size() {
return stringNum;
}
void insert(const char * str);
void clear() {
memset(nodeArray, 0, sizeof(nodeArray));
memset(hashMapBucket, 0, sizeof(hashMapBucket));
stringNum = 0;
availableNodeArrayPos = 1;
}
};
int HashMap::hash(const char * str, int hash_table_size) {
unsigned int hash=0;
unsigned int x=0;
while(*str){
hash=hash<<4+(*str++);//将hash值左移4位后加上字符ascii
x=hash&0xF0000000;
if(x){//因为下一步仍要左移4位,所以如果高4位不为0,进行下面处理,防止丢失信息
hash^=x>>24;//将高4位与5~8位异或
hash&=~x;//清除最高四位
}
return hash%hash_table_size;//对哈希表大小取余
}
}
void HashMap::insert(const char * str) {
int hval = hash(str);
if (hashMapBucket[hval] == 0) { // first insert
stringNum++;
hashMapBucket[hval] = availableNodeArrayPos;
nodeArray[availableNodeArrayPos].nextNodePos = 0;
memcpy(nodeArray[availableNodeArrayPos].content, str, strlen(str));
availableNodeArrayPos++;
} else { // inserted
int curNodePos = hashMapBucket[hval];
while(1) {
if (!curNodePos) {
break;
} else {
//same !
// printf("strcmp %s %s\n", nodeArray[curNodePos].content, str);
if (!strcmp(nodeArray[curNodePos].content, str)) {
return;
} else {
curNodePos = nodeArray[curNodePos].nextNodePos;
}
}
}
// new node
stringNum++;
nodeArray[availableNodeArrayPos].nextNodePos = hashMapBucket[hval];
memcpy(nodeArray[availableNodeArrayPos].content, str, strlen(str));
hashMapBucket[hval] = availableNodeArrayPos;
availableNodeArrayPos++;
}
// printf("%s %d %d\n", str, stringNum, hval);
}
HashMap trainSet;
//str1 + str2 -> dest
void myStrcat(char * str1, char * str2, char * dest) {
int length1 = strlen(str1);
int length2 = strlen(str2);
strncpy(dest, str1, length1);
strncpy(dest + length1, str2, length2);
dest[length1 + length2] = 0;
}
void getTrainCombinationNum(const char * train) {
int trainLength = strlen(train);
trainSet.clear();
if (trainLength == 1) {
printf("1\n");
return;
} else {
for (int i = 1; i <= trainLength -1; i++) {
char str1[80];
char str2[80];
char str3[80];
char str4[80];
char tmp[80];
strncpy(str1, train, i);
strncpy(str2, train + i, trainLength - i);
str1[i] = 0;
str2[trainLength - i] = 0;
memcpy(str3, str1, sizeof(str1));
memcpy(str4, str2, sizeof(str2));
reverse(&str3[0], &str3[strlen(str3)]);
reverse(&str4[0], &str4[strlen(str4)]);
// original
//str1 + str2
trainSet.insert(train);
myStrcat(str1 ,str4, tmp);
trainSet.insert(tmp);
myStrcat(str2 ,str1, tmp);
trainSet.insert(tmp);
myStrcat(str2 ,str3, tmp);
trainSet.insert(tmp);
myStrcat(str3 ,str4, tmp);
trainSet.insert(tmp);
myStrcat(str3 ,str2, tmp);
trainSet.insert(tmp);
myStrcat(str4 ,str1, tmp);
trainSet.insert(tmp);
myStrcat(str4 ,str3, tmp);
trainSet.insert(tmp);
// string str1 = train.substr(0, i);
// string str2 = train.substr(i, trainLength - i);
// string str3 = str1;
// reverse(str3.begin(), str3.end());
// string str4 = str2;
// reverse(str4.begin(), str4.end());
// trainSet.insert(str1 + str2);
// trainSet.insert(str1 + str4);
// trainSet.insert(str2 + str1);
// trainSet.insert(str2 + str3);
// trainSet.insert(str3 + str2);
// trainSet.insert(str3 + str4);
// trainSet.insert(str4 + str1);
// trainSet.insert(str4 + str3);
}
printf("%d\n", trainSet.size());
}
}
int main() {
int trainNum;
scanf("%d", &trainNum);
for (int i = 1; i <= trainNum; i++) {
char train[80];
// cin>>train;
scanf("%s", train);
getTrainCombinationNum(train);
}
}
算是水题吧,不过因为STL的map和set都满足不了性能需求(红黑二叉树),而hashMap/set又不在STL里,因此要自己写一个hashSet,有点小麻烦,不过之前也写过好多次了,直接利用静态预分配数组+下标模拟指针写了一个,因为这次又涉及到了字符串拼接,直接用string也会TLE,就又自己搞了一边string操作函数,hash函数直接把ELF header的hash函数拿过来用了,没啥难点,考察细心。