您的位置:首页 > 其它

hdu 5442 后缀数组(没AC)

2016-02-21 22:59 453 查看
1.后缀数组果然很好用,而且利用height 对后缀分类也很好用

2.这题要注意的是,反过来再求后缀数组之后,是要求反过来<n 序号最大的最大后缀,和正着的不一样,最后再把序号返回去

3.下面是compile error的代码……谜一般啊!dev c++能过样例……

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
//正的和反的,分别求出后缀数组,从最大的开始,如果和前面的height==N那么判断和前面的哪个更靠近开头
//(注意反过来的情况),如果height < N 输出当前的ans,这样做就不要kmp了,后缀数组果然好用!不过我还不会o(n)的算法,不知道给不给我通过哈哈
//最后判断两个位置哪个结果更小,哪个更靠前
//为什么编译错误!!!去你的!

int sa[50000];
int height[50000];
int rank[50000];
int tem[50000];
string ans1,ans2;
int k;
int n;

bool compare(int i,int j)
{
if (rank[i] != rank[j]) return (rank[i] < rank[j]);
else{
int ri = (i + k) <= n?rank[i + k]:-1;
int rj = (j + k) <= n?rank[j + k]:-1;//这里的作用是,前k个都相等之后,如果有一个第k+1是第n位,有一个不是第n位,那么是第n位的比较大(rank
除了最开始,是等于0的?
return (ri < rj);
}
}

int make_sa(string s)
{
n = s.length();
for(int i = 0; i < n;i++){
sa[i] = i;
rank[i] = s[i];
}
rank
= -1;
sa
= n;
for(k = 1; k <= n; k *= 2){
sort(sa,sa + n + 1,compare);
tem[sa[0]] = 0;
for(int i = 1; i <= n; i++){
tem[sa[i]] = tem[sa[i - 1]] + compare(sa[i - 1],sa[i]);
}
for(int i = 0; i <= n; i++){
rank[i] = tem[i];
}
}
return 0;
}

int make_height(string s)
{
n = s.length();
height[sa[0]] = 0;
int h = 0;
for(int i = 0; i < n; i++){
int j = sa[rank[i] - 1];
if (h != 0) h--;
for(;j + h < n && i + h < n && s[j + h] == s[i + h];h++);
height[rank[i]] = h;
}
return 0;
}

int main()
{
int t;
string s1,s2;
s1 = "";s2 = "";
scanf("%d",&t);
while(t--){
int nn;
cin >> nn;
ans1 = "";ans2 = "";
cin >> s1;
for(int i = 0; i < n; i++)
s2 += s1[n - i - 1];
make_sa(s1 + s1);
make_height(s1 + s1);
n = s1.length();
for(int i = 0; i < n; i++)
ans1 += s1[(sa
+ i) % n];
int pos1 = sa
;
for(int i = n; i > 0; i++){ //从最大的开始
if (height[i] < n) break; //断了,不可能有再大的
else if (sa[i - 1] < n)
pos1 = min(pos1,sa[i - 1]);
}
make_sa(s2 + s2);
make_height(s2 + s2);
n = s1.length();
for(int i = 0; i < n; i++)
ans2 += s2[(sa
+ i) % n];
int pos2 = sa
;//最大的一定是从前面开始的无疑呀
for(int i = n; i > 0; i++){//
if (height[i] < n ) break;
else if (sa[i - 1] < n)
pos2 = max(pos2,sa[i - 1]);//越大的,本来就越小
}
pos2 = n - 1 - pos2;//变成本来的位置
if (ans1 < ans2 || (ans1 == ans2 && pos1 <= pos2)) printf("%d 0\n",pos1 + 1);
else printf("%d 1\n",pos2 + 1);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm 字符串 算法