ural 1297 最長迴文子串 字尾陣列
http://acm.timus.ru/problem.aspx?space=1&num=1297
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.
InputThe 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.
OutputThe longest substring with mentioned property. If there are several such strings you should output the first of them.
Sample
|
給定一個字串,求出其最長迴文子串,若有長度相同的,輸出最左邊的。
解題思路:
字尾陣列的應用,首先,將原串倒置後拼接在其後,二者之間新增一個絕對不會再字串中出現的字元作為分隔。然後求取拼接後的字串字尾的最長公共字首就是答案。窮舉每一位i,以i為中心的最長迴文串,則只需要求出i+1和i-1倒過來的字尾最長公共字首,或者求出i和i-1(偶數長度迴文串)倒過來的最長公共字首,所以只需要將原串反轉放到原串後面然後求出height再用LCP列舉求出長度即可。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
const int maxn=211111;
/******************************************************************
** 字尾陣列 Suffix Array
** INIT:solver.call_fun(char* s);
** CALL: solver.lcp(int i,int j); //字尾i與字尾j的最長公共字首
** SP_USE: solver.LCS(char *s1,char* s2); //最長公共字串
******************************************************************/
struct SuffixArray
{
int r[maxn];
int sa[maxn],rank[maxn],height[maxn];
int t[maxn],t2[maxn],c[maxn],n;
int m;//模板長度
void init(char* s)
{
n=strlen(s);
for (int i=0; i<n; i++) r[i]=int(s[i]);
m=300;
}
int cmp(int *r,int a,int b,int l)
{
return r[a]==r[b]&&r[a+l]==r[b+l];
}
/**
字元要先轉化為正整數
待排序的字串放在r[]陣列中,從r[0]到r[n-1],長度為n,且最大值小於m。
所有的r[i]都大於0,r[n]無意義演算法中置0
函式結束後,結果放在sa[]陣列中(名次從1..n),從sa[1]到sa[n]。s[0]無意義
**/
void build_sa()
{
int i,k,p,*x=t,*y=t2;
r[n++]=0;
for (i=0; i<m; i++) c[i]=0;
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 (k=1,p=1; k<n; k*=2,m=p)
{
for (p=0,i=n-k; i<n; i++) y[p++]=i;
for (i=0; i<n; i++) if (sa[i]>=k) y[p++]=sa[i]-k;
for (i=0; i<m; i++) c[i]=0;
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];
swap(x,y);
p=1;
x[sa[0]]=0;
for (i=1; i<n; i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],k)?p-1:p++;
}
n--;
}
/**
height[2..n]:height[i]儲存的是lcp(sa[i],sa[i-1])
rank[0..n-1]:rank[i]儲存的是原串中suffix[i]的名次
**/
void getHeight()
{
int i,j,k=0;
for (i=1; i<=n; i++) rank[sa[i]]=i;
for (i=0; i<n; i++)
{
if (k) k--;
j=sa[rank[i]-1];
while (r[i+k]==r[j+k]) k++;
height[rank[i]]=k;
}
}
int d[maxn][20];
//元素從1編號到n
void RMQ_init(int A[],int n)
{
for (int i=1; i<=n; i++) d[i][0]=A[i];
for (int j=1; (1<<j)<=n; j++)
for (int i=1; i+j-1<=n; i++)
d[i][j]=min(d[i][j-1],d[i+(1<<(j-1))][j-1]);
}
int RMQ(int L,int R)
{
int k=0;
L=rank[L];
R=rank[R];
if(L>R) swap(L,R);
L++;
while ((1<<(k+1))<=R-L+1) k++;
return min(d[L][k],d[R-(1<<k)+1][k]);
}
void LCP_init()
{
RMQ_init(height,n);
}
int lcp(int i,int j)
{
if (rank[i]>rank[j]) swap(i,j);
return RMQ(rank[i]+1,rank[j]);
}
void call_fun(char* s)
{
init(s);//初始化字尾陣列
build_sa();//構造字尾陣列sa
getHeight();//計算height與rank
LCP_init();//初始化RMQ
}
} solver;
int main()
{
char s[maxn],r[maxn];
while(~scanf("%s",s))
{
int n=strlen(s),len=n;
s[n]='#';
for(int i=n-1;i>=0;--i)
s[++n]=s[i];
s[++n]='\0';
for(n=0;s[n]!='\0';++n)
r[n]=s[n];
r[n]=0;
solver.call_fun(r);
int sum=1,id=0;
for(int i=1;i<len;i++)
{
if(2*solver.RMQ(i+1,n-i)+1>sum)
sum=2*solver.RMQ(i+1,n-i)+1,id=i-solver.RMQ(i+1,n-i);
if(2*solver.RMQ(i,n-i)>sum)
sum=2*solver.RMQ(i,n-i),id=i-solver.RMQ(i,n-i);
}
for(int i=id;i<id+sum;i++)
cout<< s[i];
cout<<endl;
}
return 0;
}
/**
ThesampletextthatcouldbereadedthesameinbothordersArozaupalanalapuazorA
**/
相關文章
- URAL 1297. Palindrome(字尾陣列求最大回文串)陣列
- POJ 3294 Life Forms(字尾陣列求k個串的最長子串)ORM陣列
- SPOJ 687. Repeats(字尾陣列求最長重複子串)陣列
- java 最長迴文子串Java
- poj 2774 求兩字串的最長公共子串 字尾陣列字串陣列
- POJ 3693 Maximum repetition substring(字尾陣列求最長重複子串)陣列
- POJ 1743 Musical Theme (字尾陣列,求最長不重疊重複子串)陣列
- POJ 2217-Secretary(字尾陣列+高度陣列-最大公共子串長度)陣列
- 演算法-兩最長迴文子串演算法
- LEECODE 5 求最長迴文子串
- [動態規劃] 六、最長迴文子串動態規劃
- LeetCode 5.最長迴文子串LeetCode
- 演算法之字串——最長迴文子串演算法字串
- Amazon面試題:尋找最長迴文子串面試題
- 今日面試題:最長迴文子串;及迴文分割分析面試題
- POJ 2774-Long Long Message(字尾陣列+高度陣列-最大公共子串長度)陣列
- Leetcode[字串] 5. 最長迴文子串LeetCode字串
- LeetCode-5. 最長迴文子串(Manacher)LeetCode
- 翻譯數字串;及最長迴文子串分析字串
- HDU 4622 Reincarnation( 任意區間子串的長度, 字尾陣列+RMQ)陣列MQ
- 最長公共子串 二維陣列 Go實現陣列Go
- leedcode-最長迴文串
- 最長迴文子串 V2(Manacher演算法)演算法
- 程式碼隨想錄day46 || 647 迴文子串, 516 最長迴文子序列
- 每日一道 LeetCode (48):最長迴文子串LeetCode
- [LeetCode] Longest Palindromic Substring 最長迴文子串LeetCode
- POJ 3415-Common Substrings(字尾陣列+單調棧-公共子串的長度)陣列
- 最長子串
- 每天一道演算法題:最長迴文子串演算法
- LeetCode - 409 - 最長迴文串LeetCode
- SPOJ 220. Relevant Phrases of Annihilation(字尾陣列多次不重疊子串)陣列
- lc1771 由子序列構造的最長迴文串的長度
- Leetcode5: Longest Palindromic Substring(最長迴文子串)LeetCode
- hdu5371 最長迴文子串變形(Manacher演算法)演算法
- 978 最長湍流子陣列陣列
- HDU 3068 最長迴文(Manacher演算法解決最長迴文串問題)演算法
- HDU 5769-Substring(字尾陣列-不相同的子串的個數)陣列
- poj3080-kmp+列舉子串 求最長公共子串KMP