【技巧:字符串同构】Avendesora

判断字符串“同构”的技巧

题目大意

给定A,B两个序列,要求B在A中出现的次数以及位置。定义字符变换:把所有相同的字符变为另一种字符;两个字符串相等:当且仅当一个字符串可以在若干次字符变换之后变为另一个字符串。

题目分析

如果没有这个“字符变换”的条件,显然就是裸的KMP题。

不过有一种判断同构的方法:将数列权值转为它离之前最近相同元素的距离

用$lst[i]$表示$a[i]$元素前的最近元素位置,就是$a[i]=i-lst[i]$。

那么再接下去做kmp就好了。

 1 #include<bits/stdc++.h>
 2 const int maxn = 1000035;
 3 
 4 int T,c,n,m;
 5 int a[maxn],b[maxn],lsta[maxn],lstb[maxn],pre[maxn];
 6 int fail[maxn];
 7 int ans[maxn];
 8 
 9 int read()
10 {
11     char ch = getchar();
12     int num = 0;
13     bool fl = 0;
14     for (; !isdigit(ch); ch = getchar())
15         if (ch=='-') fl = 1;
16     for (; isdigit(ch); ch = getchar())
17         num = (num<<1)+(num<<3)+ch-48;
18     if (fl) num = -num;
19     return num;
20 }
21 int main()
22 {
23     freopen("ex_t2.in","r",stdin);
24     T = read(), c = read();
25     while (T--)
26     {
27         memset(fail, 0, sizeof fail);
28         memset(pre, 0, sizeof pre);
29         ans[0] = 0, n = read(), m = read();
30         for (int i=1; i<=n; i++)
31         {
32             a[i] = read();
33             lsta[i] = pre[a[i]];
34             pre[a[i]] = i;
35         }
36         memset(pre, 0, sizeof pre);
37         for (int i=1; i<=m; i++)
38         {
39             b[i] = read();
40             lstb[i] = pre[b[i]];
41             pre[b[i]] = i;
42         }
43         for (int i=1, j=0; i<m; i++)
44         {
45             while (j&&lstb[j+1]!=std::max(lstb[i+1]-i+j, 0)) j = fail[j];
46             if (lstb[j+1]==std::max(lstb[i+1]-i+j, 0)) j++;
47             fail[i+1] = j;
48         }
49         for (int i=0, j=0; i<n; i++)
50         {
51             while (j&&lstb[j+1]!=std::max(lsta[i+1]-i+j, 0)) j = fail[j];
52             if (lstb[j+1]==std::max(lsta[i+1]-i+j, 0)) j++;
53             if (j==m){
54                 ans[++ans[0]] = i-m+2;
55                 j = fail[j];
56             }
57         }
58         printf("%d\n",ans[0]);
59         for (int i=1; i<=ans[0]; i++) printf("%d ",ans[i]);
60         puts("");
61     }
62     return 0;
63 }

END

猜你喜欢

转载自www.cnblogs.com/antiquality/p/9426125.html