字尾陣列 最長回文字串 ural1297

2022-04-28 15:18:15 字數 1478 閱讀 4395

題意:求一串字串的最長回文字串.......

思路:在原串後面加乙個獨一無二的字元,再把原串倒過來接在原串後面。這樣,要是有回文串的話,其必然有兩個字尾的字首相同這樣,我們就可以列舉以每個字元為(k)中心的回文串,再找到它倒過來後所對應的那個位置2*len-sa[k],找到排在這之間的最小height值,也就是這兩個字串的最長公共字首,也就是以(k)位置為中心的回文串.......根據height陣列特性,lcp(i,j)=min(height[i+1],height[i+2].......height[j]),再用rmq演算法對lcp(i,j)處理到時間複雜度為o(nlogn),這樣結果就出來了,當然,以某個字元為中心的時候,要分奇偶.......

**:

#include#include#includeusing namespace std;

#define maxn 210000

#define max(x,y) x>y? x:y

#define min(x,y) x>y? y:x

int dp[maxn][32],log2[maxn];

int wa[maxn],wb[maxn],wsf[maxn],wv[maxn],sa[maxn];

int rank[maxn],height[maxn],s[maxn];

char str[maxn];

int cmp(int *r,int a,int b,int k)

void getsa(int *r,int *sa,int n,int m)

s[j]=0;

int len1=j;

getsa(s,sa,len1+1,58);

getheight(s,len1);

rmq_init(len1);

int sum=0;

int cnt=0,maxx=0,qd=0,w=0;

for(int i=1;iheight[i] ? height[i]:cnt;

if(sa[i]rank[tmp])

qq=i;

else

qq=rank[tmp];

int k=rmq(pp+1,qq);

if(maxxsa[i]))

if(k>cnt)}}

cnt=0;

int w1=0;

for(int i=1;iheight[i]) ? height[i] : cnt;

if(!sa[i])

continue;

if(sa[i]rank[tmp])

qq=i;

else

qq=rank[tmp];

int k=rmq(pp+1,qq);

if(maxx<=k)

else if(maxxsa[i])))

}if(k>cnt)}}

if(w==1)

else

}if(w==0)

printf("\n");

}return 0;

}

ural 1297 字尾陣列 最長回文子串

題意 給出乙個字串求最長回文子串 題,把字串反過來複製一遍到後邊,中間用乙個沒出現的字元隔開,然後就是列舉當以i位置為中間位時的最長回文串 是多大,就是求這中間的heigh陣列的最小值。用rmq預處理。列舉位置時分回文串長度是奇數還是偶數。include include include using ...

URAL 1297 字尾陣列 求最長回文子串

思路 這題下午搞了然後一直wa,後面就看了discuss,裡面有個陣列 abcdefdcba,這個我輸出abcd,所以錯了。然後才知道自己寫的字尾陣列對這個回文子串有bug,然後就不知道怎麼改了。然後看題解,裡面都是用rmq先預處理任意兩個字尾的最長公共字首,因為不太知道這個,所以又看了一下午,嘛嘛...

URAL 1297 最長回文子串

窮舉每一位,然後計算以這個字元為中心的最長回文子串。注意這裡要分兩種情況,一是回文子串的長度為奇數,二是長度為偶數。兩種情況都可以轉化為求乙個字尾和乙個反過來寫的字尾的最長公共字首。具體的做法是 將整個字串反過來寫在原字串後面,中間用乙個特殊的字元隔開。這樣就把問題變為了求這個新的字串的某兩個字尾的...