【后缀数组】【最长回文子串】Palindrome Ural_1297
2013-04-11 15:01
453 查看
Ural_1297. Palindrome
Time Limit: 1.0 secondMemory 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; }
相关文章推荐
- URAL 1297. Palindrome(后缀数组 求最长回文子串)
- ural 1297 Palindrome求最长连续回文子串(后缀数组求法)
- URAL - 1297 Palindrome(后缀数组求最长回文子串)
- URAL 1297 Palindrome【后缀数组】求最长回文子串
- URAL 1297 Palindrome(后缀数组求最长回文子串)
- URAL 1297 Palindrome(最长回文子串:后缀数组)
- Ural1297(Palindrome)求最长回文子串(后缀数组)
- 【后缀数组|最长回文子串】URAL-1297 Palindrome
- 后缀数组 - 求最长回文子串 + 模板题 --- ural 1297
- ural 1297 后缀数组 最长回文子串
- URAL 1297 最长回文子串(后缀数组)
- ural 1297 Palindrome (后缀数组 最长回文)
- URAL 1297 最长回文子串(后缀数组)
- 后缀数组 - 求最长回文子串 + 模板题 --- ural 1297
- URAL 1297 后缀数组:求最长回文子串
- URAL 1297 后缀数组:求最长回文子串
- ural 1297(求最长回文子串,后缀数组)
- 【URAL】1297 Palindrome 【后缀数组+RMQ——求最长回文子串】
- 【Ural 1297】Palindrome manacher 最长回文子串
- Ural 1297 Palindrome(后缀数组+最长回文子串)