題意:
給乙個字串,提供兩種操作,操作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 ...