洛谷P2336 喵星球上的點名

2022-04-30 10:15:07 字數 3405 閱讀 7755

解:sam + 線段樹合併 + dfs序。

姓和名之間插入特殊字元,轉化為下題:

給定串集合s,t,問s中每個串包含了t中的幾個串?t中每個串被多少個s中的串包含?

解:對s建廣義sam,並線段樹合併維護每個節點有多少串。

t中每個串在s的sam上跑,如果沒能跑完就被包含0次。否則答案就是到達的節點上的串數。第二問解決。

標記t中每個串最後到達的節點。s中每個串跑s的sam會得到若干個點。統計這些點到根路徑的並集上的標記個數即可。

按dfs序排序,加上每個節點到根路徑的貢獻,減去相鄰節點lca到根路徑的貢獻。第一問解決。

1 #include 2

3const

int n = 400010, m = 10000010;4

5struct

edge edge[n]; int

tp;8

9 std::maptr[n];

10int fail[n], len[n], tot = 1

, e[n], n, m, siz[n], ed[n],

11 stk[n], top, num2, pos2[n], st[n << 1][22], pw[n << 1

], d[n];

12int

ls[m], rs[m], num, sum[m], rt[n];

13 std::vectorstr[n];

1415 inline void add(int x, int

y) 22

23 inline bool cmp(const

int &a, const

int &b)

2627

void insert(int p, int l, int r, int &o)

33int mid = (l + r) >> 1;34

if(p <=mid) insert(p, l, mid, ls[o]);

35else insert(p, mid + 1

, r, rs[o]);

36 sum[o] = sum[ls[o]] +sum[rs[o]];

37return;38

}3940int merge(int x, int

y) 49

50int ask(int l, int r, int l, int r, int

o) 58

59void dfs_1(int

x) 69

return;70

}7172 inline void

prework() 81}

82return;83

}8485 inline int lca(int x, int

y) 95

96void dfs_2(int

x) 103

return

;104

}105

106 inline int split(int p, int

f) 117

return

nq;118

}119

120 inline int insert(int p, int f, int

id)

127else

130 insert(id, 1

, n, rt[np]);

131return

np;132

}133 np = ++tot;

134 len[np] = len[p] + 1

;135

while(p && !tr[p].count(f))

139if(!p)

142else

147else

150}

151 insert(id, 1

, n, rt[np]);

152return

np;153

}154

155void

out(int l, int r, int

o) 161

int mid = (l + r) >> 1

;162

out(l, mid, ls[o]);

163out(mid + 1

, r, rs[o]);

164return

;165

}166

167 inline void

clear()

172for(int i = 1; i <= num; i++)

175 tp = num = 0

;176 tot = 1

;177

return

;178

}179

180int

main()

190 str[i].push_back(-1

);191 p = insert(p, -1

, i);

192 scanf("

%d", &k);

193for(int j = 1; j <= k; j++)

198}

199///

build

200for(int i = 2; i <= tot; i++)

204 dfs_1(1

);205

206for(int i = 1; i <= m; i++)

214if(!fd)

218 printf("

%d\n

", ans);

219}

220221 dfs_2(1

);222

prework();

223224

for(int i = 1; i <= n; i++)

231 std::sort(stk + 1, stk + top + 1

,cmp);

232 top = std::unique(stk + 1, stk + top + 1) - stk - 1

;233

int ans = 0

;234

for(int j = 1; j <= top; j++)

238 printf("

%d "

, ans);

239}

240241

return0;

242 }

ac**

ac自動機解法。

喵星球上的點名

a180285幸運地被選做了地球到喵星球的留學生。他發現喵星人在上課前的點名現象非常有趣。假設課堂上有n個喵星人,每個喵星人的名字由姓和名構成。喵星球上的老師會選擇m個串來點名,每次讀出乙個串的時候,如果這個串是乙個喵星人的姓或名的子串,那麼這個喵星人就必須答到。然而,由於喵星人的字碼過於古怪,以至...

SCOI2012 喵星球上的點名

有n個串,代表n個人的姓氏和名字,都是用很多個數字表示的,比如我姓1,2,3,4,名4,5,6,7。然後有m個點名串,如果點到了某個人的姓或名裡面的某一串,那個人就被點到,不過乙個人在乙個點名串中只能被點一次。比如點名串是2,3,4,我的姓中含有2,3,4,那麼我就會被叫到。求每個學生分別被叫到多少...

SCOI2012 喵星球上的點名

給出n個模式串,m個文字串,每個模式串由兩部分組成,我們認為乙個模式串被乙個文字串包含只要這個文字串包含它的兩部分中的其中一部分的子串。求每個文字串包含多少個模式串,每個模式串又被多少個文字串包含。1 n 20000,1 m 50000,模式串總長和文字串的總長分別不超過100000 保證模式串和文...