poj 2758 字尾陣列

2021-08-03 22:04:47 字數 3052 閱讀 5136

題意:

給乙個字串,提供兩種操作,操作i:在 當前 第i個字元之前插入字元c;操作q:求 原序列 字尾i,與字尾j的lcp,計算lcp時應把插入字元一起算上

思路:

確實沒看出來這玩意能用字尾陣列搞……

啊本題有好幾個坑需要額外注意:

1. 插入時候的位置指的上當前序列;

2. 詢問的位置指的是原序列,然後插入字元應計入比較;

3. 題目僅僅是說 engligh letter 而非 lower case letter,wa了半天才找到 - -|||;

4. i操作的步數非常少,最多200次

先拋開插入操作考慮詢問操作,求乙個序列任意兩個字尾的lcp,顯然字尾陣列加rmq,實現方式為對height陣列做預處理,查詢rmq(rank[i],rank[j]);然後考慮插入,因為插入的運算元非常少,對於詢問,可以先找到i和j的原序列lcp,再找到最近的乙個插入在i,j後的字元距離i,j的位置k(這裡找到最近的插入字元位置我是用set自帶的平衡二叉樹來加速查詢),分情況討論。

1. 如果lcp < k-1,顯然插入字元對查詢值無影響;

2. 如果lcp >= k-1,則從k位置開始,用t1,t2逐個指向當前序列中的字元,直至t1,,t2指向的均為原序列中的字元為止,然後遞迴查詢t1,t2

本題在思路上不是特別麻煩,難點在看清題目的表述,以及實現能力上

#include 

#include

#include

#include

#include

#include

using

namespace

std;

const

int maxint = 0x7fffffff;

const

int maxsize = 5 * 1e4 + 100;

vector

ins[maxsize];

set inset;

#define rep(i,n) for(int i = 0; i < n; i++)

int rk[maxsize], sa[maxsize], height[maxsize], wa[maxsize], res[maxsize];

char w[maxsize];

int len;

void getsa(int up)

int d = 1, p = 0;

while (p < len)

swap(k, r);

p = 0;

k[sa[0]] = p++;

rep(i, len - 1)

if (p >= len) return;

d <<= 1, up = p, p = 0;

} } void getheight()

height[rk[i]] = h;

} } void getsuffix()

w[len] = 0;

getsa(up + 1);

getheight();

} int a[maxsize];

int dmin[maxsize][32];

void rmq_init(int a, int len)

for (int j = 1; (1

<< j) <= len; ++j)

for (int i = 0; i + (1

<< j) - 1

1], dmin[i + (1

<< (j - 1))][j - 1]);

} return;

} int rmq_min(int l, int r)

void sinsert(char c, int p)

else

ins[i].push_back(c);

inset.insert(i);

//cout<<"insert: "break;

} cnt++;

} if (!flag)

inset.insert(len);

//cout<<"insert: "<}

} int query(int s1,int s2)

if (s1>s2) swap(s1,s2);

int lcp;

if (rk[s1] < rk[s2]) lcp = rmq_min(rk[s1] + 1,rk[s2]);

else lcp = rmq_min(rk[s2] + 1,rk[s1]);

ans = lcp;

//cout<<"rmq_lcp: "set

::iterator t1 = inset.upper_bound(s1);

set::iterator t2 = inset.upper_bound(s2);

if (t1!=inset.end())

t = t < *t1-s1 ? t : *t1-s1;

if (t2!=inset.end())

t = t < *t2-s2 ? t : *t2-s2;

//cout<<"t: " t-1)

else

ic = w[i];

i++;

i1 = 0;

} //cout<<"ic: "else

jc = w[j];

j++;

j1 = 0;

} //cout<<"jc: "else flag = false;

//if (i == len || j == len) flag = false;

} if (!flag) return ans;

else

} else

return ans;

} int main()

else

} return

0;

}

poj 3294 字尾陣列

題意 給定n個串,求最長的子串s,使得s為其中超過一半的串的公共子串。題解 字尾陣列,按height陣列分組,按sa陣列輸出。include include include using namespace std const int maxn 200000 int s maxn w maxn wa ...

poj 1743 字尾陣列

字尾陣列,求不可重疊最長重複字串。include include include include include include define maxd 21000 using namespace std int r maxd rank maxd height maxd int sa maxd wa...

字尾陣列 poj 3693

題目 給出乙個串,求重複次數最多的連續重複子串 列舉長度為l,然後看長度為l的字串最多連續出現幾次。既然長度為l的串重複出現,那麼str 0 str l str 2 l 中肯定有兩個連續的出現在字串中。那麼就列舉連續的兩個,然後從這兩個字元前後匹配,看最多能匹配多遠。即以str i l str i ...