題目鏈結
先考慮68分的做法:
求在a串**現,且在b串中沒出現的串的數量。
使用容斥,用a的不同子串數減去a,b的不同公共子串數。
先用雙指標,求出a的每個位置開始,在b中最多能向後匹配多遠。
然後,問題變為,給你一些區間,問它們的子區間中有多少不同的串。
因為每個串,都是原區間\([l,r]\)中\([l,i]\)的字尾。\((l<=i<=r)\)
而字尾就是在前面去掉一些字元,就是不斷走fa。
所以可以建出fa邊的樹,然後定位出這些位置,求這些點到根的路徑的並。
使用樹鏈合併即可,要注意壓縮的問題。
100分做法:與68基本相同,就是判斷子串\([a,b]\)是否出現多了乙個限制(\(l<=a,b<=r\))。
而乙個串匹配的位置,就是這個點子樹中紅點的集合。
紅點對應字首,所以這個限制可以轉化為字首位置的限制。
需要判斷乙個點的子樹中是否有x~y的數。使用dfs序+主席樹即可。
#include #include #define ll long long
int fr[2000010],ne[2000010];
int v[2000010],bs = 0;
int wl[2000010],wr[2000010],tm = 1;
int xl[2000010];
struct sam
void clean()
np = sl = 1;
}void insert(char c, int wz)
if (p == 0) fa[np] = 1;
else }}
red[np] = wz;
}};void addb(int a, int b)
sam s,t;
void dfs1(int u)
int up[1000010];
char zf[1000010];
struct spx
spx(int u, int cd)
};spx px[1000010];
ll baoli(int s)
}ll rtn = 0;
for (int i = 2; i <= t.sl; i++) rtn += up[i];
return rtn;
}int he[24000010],cl[24000010],cr[24000010],sl = 0;
int jianshu(int l, int r)
int xiugai(int i, int l, int r, int j, int x)
cl[rt] = cl[i];
cr[rt] = cr[i];
int m = (l + r) >> 1;
if (j < m) cl[rt] = xiugai(cl[rt], l, m, j, x);
else cr[rt] = xiugai(cr[rt], m, r, j, x);
he[rt] = he[cl[rt]] + he[cr[rt]];
return rt;
}int chaxun(int i, int l, int r, int l, int r)
int gen[1000010],n;
bool zichuan(int i, int l, int r, int cd)
int main()
int m;
scanf("%d", &m);
for (int i = 0; i < m; i++)
}ll zo = 0;
for (int j = 1; j <= t.sl; j++) zo = zo + t.len[j] - t.len[t.fa[j]];
printf("%lld\n", zo - baoli(s));
}return 0;
}
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 的情況。大體思路就是求出...