测评会员优惠活动进行中 · 开通 VIP,有效期内测评不限次 VIP 优惠中 · 测评不限次 立即查看

A19506. 谐音替换(replace)

填空题 较易

题目描述

谐音替换(replace)

题目描述

小 W 是一名喜欢语言学的算法竞赛选手。在语言学中,谐音替换是指将原有的字词替换为读音相同或相近的字词。小 W 发现,谐音替换的过程可以用字符串来进行描述。具体地,小 W 将谐音替换定义为以下字符串问题:

给定 n 个字符串二元组,第 i(1 ≤ i ≤ n)个字符串二元组为 (si,1, si,2),满足 |si,1| = |si,2|,其中 |s| 表示字符串 s 的长度。

对于字符串 s,定义 s 的替换如下:

对于 s 的某个子串 y,若存在 1 ≤ i ≤ n 满足 y = si,1,则将 y 替换为 y' = si,2。具体地,设 s = x + y + z,其中 x 和 z 可以为空,“+” 表示字符串拼接,则 s 的替换将得到字符串 s' = x + y' + z。

小 W 提出了 q 个问题,第 j(1 ≤ j ≤ m)个问题会给定两个不同的字符串 tj,1, tj,2,她想知道有多少种字符串 tj,1 的替换能够得到字符串 tj,2。两种 s 的替换不同当且仅当子串 y 的位置不同或用于替换的二元组 (si,1, si,2) 不同,即 x,z 不同或 i 不同。你需要回答小 W 提出的所有问题。

输入格式

从文件 replace.in 中读入数据。

输入的第一行包含两个正整数 n, q,分别表示字符串二元组的数量和小 W 提出的问题的数量。

输入的第 i+1(1 ≤ i ≤ n)行包含两个字符串 si,1, si,2,表示第 i 个字符串二元组。

输入的第 j+n+1(1 ≤ j ≤ q)行包含两个字符串 tj,1, tj,2,表示小 W 提出的第 j 个问题。

输出格式

输出到文件 replace.out 中。

输出 q 行,其中第 j(1 ≤ j ≤ q)行包含一个非负整数,表示替换后得到字符串 tj,2 的字符串 tj,1 的替换的数量。

样例 1 输入

4 2
xabcx xadex
ab cd
bc de
aa bb
xabcx xadex
aaaa bbbb

样例 1 输出

2

0

样例 1 解释

对于小 W 的第一个询问,共有 2 种 t1,1 的替换能够得到 t1,2

1.令 x,z 均为空串,y = xabcx,i=1,则 y' = xadex,替换后得到 xadex;

2.令 x = xa,y = bc,z = x,i=3,则 y' = de,替换后得到 xadex。

样例 2 输入

3 4
a b
b c
c d
aa bb
aa b
a c
b a

样例 2 输出

0
0
0
0

样例 3

见选手目录下的 replace/replace3.in 与 replace/replace3.ans。

该样例满足测试点 11, 12 的约束条件。

样例 4

见选手目录下的 replace/replace4.in 与 replace/replace4.ans。

该样例满足测试点 15, 16 的约束条件。

数据范围

设 L1 =∑n i=1 |si,1| + |si,2|,L2 = ∑q j=1 |tj,1| + |tj,2|。对于所有测试数据,保证:

1 ≤ n, q ≤ 2 × 105

2 ≤ L1, L2≤ 5 × 106

对于所有 1 ≤ i ≤ n,si,1, si,2 均仅包含小写英文字母,且 |si,1| = |si,2|;

对于所有 1 ≤ j ≤ q,tj,1, tj,2 均仅包含小写英文字母,且 tj,1 ≠ tj,2

特殊性质A:q=1。

特殊性质B:定义字符串s为特别的,当且仅当字符串s仅包含字符a和b,且字符b在s中出现恰好一次。对于所有1 ≤ i ≤ n,si,1, si,2 均为特别的,且对于所有

1≤j≤q,tj,1,tj,2均为特别的。

参考答案

#include <bits/stdc++.h> using namespace std; typedef unsigned long long ll; const int P = 1e9+7, Q=1e9+9, B=457, C=997; ll next_hash (ll prev, int chr) { ll a = prev >> 32, b = prev & -1u; chr ++; a = (a * B + chr) % P; b = (b * C + chr) % Q; return (a << 32) | b; } const int maxl = 5002424; const int maxn = 200083; struct node { int pt, nxt [27]; } trie [maxl*2+maxn]; struct pn { int rt; unordered_map <ll, int> mp; } pns [maxn]; int ctc, ptc; char s [maxl], t [maxl]; void q_diff (int len, int& dnq, int& dxq) { int nq = len+1, xq=-1; int i; for (i=0; i<len; i++) if (s [i] != t [i]) nq = min (nq, i), xq = max (xq, i); dnq = nq; dxq = xq; } #define jnode(var,chr) if(trie[var].nxt[chr])var=trie[var].nxt[chr];else var=trie[var].nxt[chr]=++ctc #define ord(ch) (ch=='#'?26:ch-'a') void add_s (int idx) { scanf ("%s%s", s, t); int len = strlen (s); if (strcmp (s, t) == 0) return; int nq, xq; q_diff (len, nq, xq); int i, cur = 0; for (i=nq; i<=xq; i++) { jnode (cur, ord (s [i])); jnode (cur, ord (t [i])); } jnode (cur, 26); for (; i<len; i++) jnode (cur, ord (s [i])); int pt = trie [cur] .pt; if (pt == 0) pt = trie [cur] .pt = ++ptc; cur = pns [pt] .rt; if (cur == 0) cur = pns [pt] .rt = ++ctc; for (i=nq-1; i>=0; i--) jnode (cur, ord (s [i])); trie [cur] .pt ++; } void dfs_pn (int rt, int cur, ll ch, int cn) { pns [rt] .mp [ch] = cn = trie [cur] .pt += cn; int i, m; for (i=0; i<27; i++) if (m = trie [cur] .nxt [i]) dfs_pn (rt, m, next_hash (ch, i), cn); } ll hashes [maxl]; int query (void) { scanf ("%s%s", s, t); int len = strlen (s); if (strlen (t) != len) return 0; int nq, xq; q_diff (len, nq, xq); int i, cur = 0; for (i=1; i<=nq; i++) hashes [i] = next_hash (hashes [i-1], ord (s [nq-i])); for (i=nq; i<=xq; i++) { if (0 == (cur = trie [cur] .nxt [ord (s [i])])) return 0; if (0 == (cur = trie [cur] .nxt [ord (t [i])])) return 0; } if (0 == (cur = trie [cur] .nxt [26])) return 0; int ans = 0; for (i=xq; i<len; i++) { if (trie [cur] .pt != 0) { int l = 0, r = nq; pn& cpn = pns [trie [cur] .pt]; while (l < r) { int m = l+r+1 >> 1; if (cpn.mp.count (hashes [m])) l = m; else r = m-1; } ans += cpn.mp [hashes [l]]; } if (i != len-1) if (0 == (cur = trie [cur] .nxt [ord (t [i+1])])) break; } return ans; } int main (void) { int n, q; scanf ("%d%d", &n, &q); int i; for (i=1; i<=n; i++) add_s (i); for (i=1; i<=ptc; i++) dfs_pn (i, pns [i] .rt, 0, 0); for (i=1; i<=q; i++) printf ("%d\n", query ()); }
上一题 下一题