- 题意:给出n(1 <= n <= 100)个长度为m(1 <= m <= 50)的字符串,可任意选择其中的字符串,问能构成的回文串长度最大是多少,并且要求输出最长回文串。
思路
因为n只有100,所以直接暴力!!哈希大水题!!(QAQ,没看数据范围,最后竟然还用了马拉车……,那份代码太丑了,不贴了
我们定义两个has1[ ]、has2[ ]分别用来存正串的哈希值和反串的哈希值。
对于每一个串s[ i ],我们枚举其他s[ j ]对应的反串看是不是哈希值相同。相同说明s[ i ]和s[ j ]是对称的,就可以加到答案的两边,构成答案回文串的一部分。
尝试匹配完所有的字符串之后,我们还要考虑没被匹配过字符串本身是不是回文串,注意我们只能在中间加一个回文串。
输出答案
END
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
typedef unsigned long long ull;
inline int read()
{
int x = 0, f = 1; char c = getchar();
while(c < '0' || c > '9') { if(c == '-') f = -f; c = getchar(); }
while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
return x * f;
}
const int maxN = 105;
const ull base = 2333;
ull has1[maxN], has2[maxN];
int n, m;
char s[maxN][55];
bool vis[maxN];
struct node{
string _0, _1;
int num;
node(string a = "", string b = "", int c = 0): _0(a), _1(b), num(c) {}
};
void init()
{
for(int i = 0; i <= n; ++ i )
has1[i] = has2[i] = 0, vis[i] = false;
}
int main()
{
n = read(); m = read();
init();
for(int i = 0; i < n; ++ i )
{
cin >> s[i];
int len = strlen(s[i]);
for(int j = 0; j < len; ++ j )
{
has1[i] = has1[i] * base + ull(s[i][j] - 'a' + 1);
has2[i] = has2[i] * base + ull(s[i][len - 1 - j] - 'a' + 1);
}
}
node ans;
for(int i = 0; i < n; ++ i )
{
if(vis[i]) continue;
for(int j = 0; j < n; ++ j )
{
if(i != j && has1[i] == has2[j])
{
ans._0 = ans._0 + s[i];
ans._1 = s[j] + ans._1;
ans.num += (m << 1);
vis[i] = vis[j] = true;
}
}
}
for(int i = 0; i < n; ++ i )
{
if(vis[i]) continue;
if(has1[i] == has2[i])
{
ans._0 += s[i], ans.num += m;
break;
}
}
cout << ans.num << endl << ans._0 + ans._1 << endl;
return 0;
}