您的位置:首页 > 其它

HDU 5510 Bazinga(技巧 + 字符串哈希)

2015-11-02 17:52 337 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5510

题意:

依次给出n个串, 找出下标最大且不能包含前面所有的串的串(即前面所有的串都是这个串的子串)。

分析:

这道题我一开始的想法是AC自动机, 但是数据太大就MLE;就换了种思路。 其实可以发现, 如果a是b的子串,b是c的子串, 那么就不虚要比较a和c就能得到a也是c子串。 所以我们只需把所有互不包含的串的下标存起来, 来一个新串就和他们比较, 把是新串的子串的串清除出去即可了。这样一直进行下去最后一个不能包含前面的串的新串就是答案。 比较一个串是否包含另一串,快速的方法就是字符串哈希。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
typedef unsigned long long ULL;
#define SEED 1000000007

const int maxn = 2010;
const int N = 505;
int p[maxn], pos;
char s
[maxn];
ULL k[maxn], Hash[maxn], hash_[maxn];
void init()
{
k[0] = 1;
for(int i = 1; i < maxn; i++)
k[i] = k[i-1] * SEED;
}
bool Pa(int len)
{
int id = p[pos-1];
int L = strlen(s[id]);
hash_[L] = 0;
for(int i = L-1; i >= 0; i--)
hash_[i] = hash_[i+1] * SEED + s[id][i]-'a'+1;
for(int i = 0; i <=len-L; i++)
{
if(hash_[0] == Hash[i]-Hash[i+L]*k[L])
return true;
}
return false;
}
int main()
{
int T, n, len, ans;
scanf("%d", &T);
init();
for(int cas = 1; cas <= T; cas++)
{
scanf("%d", &n);
pos = 0;
ans = -1;
for(int i = 1; i <= n; i++)
{
scanf("%s", s[i]);
len = strlen(s[i]);
Hash[len] = 0;
for(int j = len-1; j >= 0; j--)
Hash[j] = Hash[j+1] * SEED + s[i][j]-'a'+1;
while(pos)
{
if(Pa(len))
pos--;
else
{
ans = i;
break;
}
}
p[pos++] = i;
}
printf("Case #%d: %d\n", cas, ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: