NOI2018 你的名字

2022-07-25 20:03:14 字數 2172 閱讀 3131

實力強大的小 a 被選為了 ion2018 的出題人,現在他需要解決題目的命名問題。

小 a 被選為了 ion2018 的出題人,他精心準備了一道質量十分高的題目,且已經把除了題目命名以外的工作都做好了。

由於 ion 已經舉辦了很多屆,所以在題目命名上也是有規定的,ion 命題手冊規定:每年由命題委員會規定乙個小寫字母字串,我們稱之為那一年的命名串,要求每道題的名字必須是那一年的命名串的乙個非空連續子串,且不能和前一年的任何一道題目的名字相同。

由於一些特殊的原因,小 a 不知道 ion2017 每道題的名字,但是他通過一些特殊手段得到了 ion2017 的命名串,現在小 a 有 次詢問:每次給定 ion2017 的命名串和 ion2018 的命名串,求有幾種題目的命名,使得這個名字一定滿足命題委員會的規定,即是 ion2018 的命名串的乙個非空連續子串且一定不會和 ion2017 的任何一道題目的名字相同。

由於一些特殊原因,所有詢問給出的 ion2017 的命名串都是某個串的連續子串,詳細可見輸入格式。

大概就是講給定乙個串s,每次詢問給乙個串t和l,r,需要回答s(l,r)的所有子串和t的所有子串中有多少個不一樣。

顯然我們是要找一樣的然後拿子串總數減去一樣的。

那如找相同的子串呢?

首先考慮如果l = 1, r = n,把串t放在s的sam上跑,如果有對應的轉移就轉移,否則就跳到partent上去找轉移,跳到根都沒有就匹配下乙個位置。

把t的每個位置在s的字尾自動機上匹配的長度陣列稱為p。我們構建t的字尾自動機,記錄一下字尾自動機上每個結點的任意乙個endpos。

然後我們dp的時候每個節點能貢獻的不同的子串就是max(0, len[i] - max(len[fa[i]], p[endpos[i]]);

那麼問題考慮l,r任意的情況,如何保證t只在s(l,r)的字尾自動機上匹配呢?在sam的每個結點上維護endpos就好,這裡又用了線段樹合併,這裡的線段樹的合併需要新開結點,不能破壞子結點的線段樹。

我們還是繼續把t放到s的字尾自動機上匹配,記錄匹配長度,如果有轉移,且有endpos在(l+p[i-1],r)中,就可以匹配,否則考慮減少匹配長度,當減到len[fa[x]]的時候就跳到partent上繼續匹配。

**基本是抄的。

#include #include #include #include using namespace std;

namespace seg

void ins(int &x,const int &p, int l = 1, int r = n)

int add(const int &x)

int merge(const int &x,const int &y)

int query(int x, int l, int r, int l = 1, int r = n)

}templatestruct sam

sam()

void ins(const int &x, const int &pos = 0)

void query(int &p, int &l, const int &l, const int &r, const int &x)

if (!l) return;

if (--l == len[fa[p]]) p = fa[p];}}

long long calc(int *p)

return ans;

}};sam<500050> sam1;

sam<1000050> sam2;

const int n = 5e5 + 100;

char s[n], t[n<<1];

int p[n<<1], c[n<<1], a[n<<1];

int main()

for (int i = 1; i <= sam1.tot; i++) c[sam1.len[i]]++;

for (int i = 1; i <= n; i++) c[i] += c[i-1];

for (int i = 1; i <= sam1.tot; i++) a[c[sam1.len[i]]--] = i;

for (int i = sam1.tot; i; i--)

int q;

scanf("%d", &q);

while (q--)

printf("%lld\n", sam2.calc(p));

}}

NOI2018 你的名字

題目描述 小 a 被選為了 ion2018 的出題人,他精心準備了一道質量十分高的題目,且已經把除了題目命名以外的工作都做好了。由於 ion 已經舉辦了很多屆,所以在題目命名上也是有規定的,ion 命題手冊規定 每年由命題委員會規定乙個小寫字母字串,我們稱之為那一年的命名串,要求每道 題的名字必須是...

NOI2018 你的名字

sam寫的太不熟練了 sam上的線段樹合併也不熟練 調了半天樣例 給定乙個s,q次詢問,每次給出t,l,r,求對於s l,r 屬於t的子串卻不屬於s l,r 的子串有多少個 看上去挺簡潔的乙個問題。對於s 1,n 68pts?如果做過 heoi2015 最短不公共子串 就好做多了!可以對a,b分別建...

NOI2018 你的名字

嘟嘟嘟 這題以前寫過棄掉了,後來竟然連自己的68分寫法都看不懂了 這次回首這道題,心想怎麼說也得把這題切了,哪怕抄題解也行。但沒想到別人的題解自己怎麼也看不懂,最終還是自己搞出來了 我真nb 總用時前一天下午到第二天凌晨0 30 第二天半個上午。我們先來回顧 l 1,r n 的情況。大體思路就是求出...