您的位置:首页 > 其它

【后缀数组】【最长回文子串】Palindrome Ural_1297

2013-04-11 15:01 453 查看

Ural_1297. Palindrome

Time Limit: 1.0 second

Memory Limit: 64 MB


The “U.S. Robots” HQ has just received a rather alarming anonymous letter. It states that the agent from the competing «Robots Unlimited» has infiltrated into “U.S. Robotics”. «U.S. Robots» security service would have already
started an undercover operation to establish the agent’s identity, but, fortunately, the letter describes communication channel the agent uses. He will publish articles containing stolen data to the “Solaris” almanac. Obviously, he will obfuscate the data,
so “Robots Unlimited” will have to use a special descrambler (“Robots Unlimited” part number NPRx8086, specifications are kept secret).

Having read the letter, the “U.S. Robots” president recalled having hired the “Robots Unlimited” ex-employee John Pupkin. President knows he can trust John, because John is still angry at being mistreated by “Robots Unlimited”.
Unfortunately, he was fired just before his team has finished work on the NPRx8086 design.

So, the president has assigned the task of agent’s message interception to John. At first, John felt rather embarrassed, because revealing the hidden message isn’t any easier than finding a needle in a haystack. However, after
he struggled the problem for a while, he remembered that the design of NPRx8086 was still incomplete. “Robots Unlimited” fired John when he was working on a specific module, the text direction detector. Nobody else could finish that module, so the descrambler
will choose the text scanning direction at random. To ensure the correct descrambling of the message by NPRx8086, agent must encode the information in such a way that the resulting secret message reads the same both forwards and backwards.

In addition, it is reasonable to assume that the agent will be sending a very long message, so John has simply to find the longest message satisfying the mentioned property.

Your task is to help John Pupkin by writing a program to find the secret message in the text of a given article. As NPRx8086 ignores white spaces and punctuation marks, John will remove them from the text before feeding it into
the program.

Input

The input consists of a single line, which contains a string of Latin alphabet letters (no other characters will appear in the string). String length will not exceed 1000 characters.

Output

The longest substring with mentioned property. If there are several such strings you should output the first of them.

Sample

input
ThesampletextthatcouldbereadedthesameinbothordersArozaupalanalapuazorA

output
ArozaupalanalapuazorA

又是数组开小了!!!!!已经不知道是第几次了!!!!

比如给出串 abaab,我们只需要把它反过来加入到后面,变成

abaab$baaba

然后我们利用后缀数组求出height(等会用)

我们枚举中间节点j,然后在后面的串中分长度为奇数或者偶数找到对应位置,然后求出最长公共前缀,这就药用到前面的height数组了

但是为什么这样扫描就是对的呢?我们看下面

假设找到的 j 为2(即aab$baaba),分奇偶讨论

如果是奇数,对应的位置应为9(即ba)

如果是偶数,对应的位置应为8(即aba)

这里不要绕混了,自己可以在纸上画画(我反正混了。。。。)

至于求公共前缀可以RMQ,但是我是写的O(N)的扫描,Ural数据很弱,连朴素都能过,这个后缀数组就更不说了

还有代码里面48行说了一个小的数要+1,为什么呢?

我们的height表示 i 和 i - 1 的最长公共前缀,但是 i - 1 跟我们又没关系,所以我们只需要用到 [ i + 1 , j ] 这个区间的 height 值

测评情况(Ural)



C++ AC Code

/*http://blog.csdn.net/jiangzh7
By Jiangzh*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=(1000+10)*2;
const int inf=0x3f3f3f3f;
char s
;
int n,m;
int sa
,rank
;
int tmp
,c
;//以前c是开的'z'+10,调了好久才发现也需要N的大小
int height
;

bool cmp(int *r,int a,int b,int l,int len)
{
if(a+l>len||b+l>len) return 0;
return r[a]==r[b]&&r[a+l]==r[b+l];
}

void DA(char *r,int n,int m)
{
int i,j,p,*x=rank,*y=tmp;
memset(c,0,sizeof(c));
for(i=0;i<n;i++) c[x[i]=r[i]]++;
for(i=1;i<m;i++) c[i]+=c[i-1];
for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
for(j=1,p=0;p<n;j*=2,m=p)
{
for(p=0,i=n-j;i<n;i++) y[p++]=i;
for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
memset(c,0,sizeof(c));
for(i=0;i<n;i++) c[x[y[i]]]++;
for(i=1;i<m;i++) c[i]+=c[i-1];
for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
for(swap(x,y),p=1,x[sa[0]]=0,i=1;i<n;i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j,n-1)?p-1:p++;
}
for(i=0;i<n;i++) rank[sa[i]]=i;
int k=0;
for(i=0;i<n;height[x[i++]]=k)
for(k?k--:0,j=sa[x[i]-1];r[i+k]==r[j+k];k++);
}

int solve(int i,int j)
{
if(i>j) swap(i,j);
i++;//小的那个数+1,为什么见上面的分析
int res=inf;
for(int x=i;x<=j;x++) res=min(res,height[x]);
return res;
}

int main()
{
freopen("URAL1297.in","r",stdin);
freopen("URAL1297.out","w",stdout);
scanf("%s",s);n=strlen(s);
int cnt=n;s[cnt++]='$';
for(int i=n-1;i>=0;i--) s[cnt++]=s[i];
s[n=cnt]='\0';m='z'+1;
DA(s,n,m);
int maxlen=0,start=0;
for(int i=0;i<n/2;i++)
{
int j=n-i-1;//长度为奇数
int k=solve(rank[i],rank[j]);
if(k*2-1>maxlen) maxlen=k*2-1,start=i-k+1;
j=n-i;//长度为偶数
k=solve(rank[i],rank[j]);
if(k*2>maxlen) maxlen=k*2,start=i-k;
}
s[start+maxlen]='\0';
puts(s+start);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: