• 【技巧:字符串同构】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
    ",ans[0]);
    59         for (int i=1; i<=ans[0]; i++) printf("%d ",ans[i]);
    60         puts("");
    61     }
    62     return 0;
    63 }

    END

  • 相关阅读:
    多线程09-Lock和Condition
    多线程08-Callable和Future
    多线程07-线程池
    在linux环境下搭建java web测试环境(非常详细!)
    Linux下的环境部署和项目发布
    Linux下安装软件命令详解
    Linux下安装Tomcat服务器和部署Web应用
    monkey实战--测试步骤、常用参数、常规monkey命令
    如何做好回归测试
    Apache转发到Tomcat
  • 原文地址:https://www.cnblogs.com/antiquality/p/9426125.html
Copyright © 2020-2023  润新知