题目:http://poj.org/problem?id=3007
题意:
给定一个字符串,从任意位置把它切为两半,得到两条子串
定义 子串1为s1,子串2为s2,子串1的反串为s3,子串2的反串为s4
现在从s1 s2 s3 s4中任意取出两个串组合,问有多少种不同的组合方法
分析:
发现字符串长度最多为72,刚开始用的string+substr+reverse构造新子串,直接用set把构造得到的新字符串保存起来,然后看看有多少即可。然而超时~~,因为保存字符串set存储和比较字符串可能会比较慢,所以先用个Hash把字符串映射成一个整数,然后在保存到set中,这样应该行了吧?。又 T ~~,然后又把substr改了,然后过了QAQ
代码:
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>
using namespace std;
typedef long long ll;
const int INF = 1e9 + 9;
const int N = 100 + 9;
string a[N][2], b[N][2];
char s[100];
unsigned int BKDRHash (string str) {
unsigned int seed = 131; // 31 131 1313 13131 131313 etc..
unsigned int hash = 0;
int i = 0;
int n = str.size();
while (i < n) {
hash = hash * seed + (str[i++]);
}
return (hash & 0x7FFFFFFF);
}
int main() {
// freopen ("f.txt", "r", stdin);
int T;
scanf ("%d", &T);
set<unsigned int>sset;
while (T-- ) {
scanf ("%s", s);
sset.clear();
int n = strlen (s);
a[1][0] = "";
a[1][0] += s[0];
for (int i = 2; i <= n - 1; i++) a[i][0] = a[i - 1][0] + s[i - 1];
b[n - 1][0] = "";
b[n - 1][0] += s[n - 1];
for (int i = n - 2; i >= 1; i--) b[i][0] = b[i + 1][0] + s[i];
for (int i = 1; i < n; i++) {
a[i][1] = a[i][0];
b[i][1] = b[i][0];
reverse (a[i][0].begin(), a[i][0].end() );
reverse (b[i][0].begin(), b[i][0].end() );
for (int j = 0; j <= 1; j++)
for (int k = 0; k <= 1; k++)
sset.insert (BKDRHash (a[i][j] + b[i][k]) ), sset.insert (BKDRHash (b[i][j] + a[i][k]) );
}
printf ("%d\n", sset.size() );
}
return 0;
}
/*
Sample Input
4
aa
abba
abcd
abcde
Sample Output
1
6
12
18
*/