zoukankan      html  css  js  c++  java
  • hihocoder #1052 基因工程

    $DeclareMathOperator{ ev}{rev}$

    传送门:基因工程 

    这道题拖了好久,一直没有清晰的思路。

    当然,$klefrac{n}{2}$ 时,比较简单。下面我着重讲一下当 $k>frac{n}{2}$ ,即前 $k$ 个字符与后 $k$ 个字符有重叠时,如何思考这个问题。

    为了便于分析,我们把题目要求形式化成如下的数学表示

    假设修改后的字符串为 $S$ ,字符串长度为 $n$ ,则 $S$ 满足

    [S_i = S_{i+n-k} qquad   1 le i le k ]

    即“$S$是以$n-k$为周期的字符串”。

    这样讲对吗?我们回忆一下数学上周期函数的概念,不难发现这个说法不确切,一个有周期性的字符串是无限长的。

    为了消除这种数学上的不严格,我们换一种说法

    满足

    [S_i = S_{i+n-k} qquad  1 le i le k]

    且长为$n$的字符串$S$,必定是某个以 $n-k$ 为周期的无限长字符串 $T$ 的子串

    至此我们找到了一个将问题大大简化了的必要条件,显然这个命题反过来也成立。因而有

    对于任意长为 $n$ 的字符串 $S$

    $S_i = S_{n-k+i}  qquad 1 le i le k, quad  0 le k le n,$

      $iff$ $S$ 是某个以 $n-k$ 为周期的无限长字符串 $T$ 的子串

    UPDATE (2019/5/16)

    另一道跟周期串有关的字符串构造题,CF1158B The minimal unique substring

    $mathsf{UPD (2018/12/27)}$

    多年以后又遇到一个类似的问题,CF1081H Palindromic Magic,想起这篇旧文。

    作者(fjzzq2002)在题解中也定义了周期串,把我所谓「$S$ 是某个以 $t$ 为周期的无限长字符串 $T$ 的子串」径称为「$S$ 以 $t$ 为周期($S$ has a period of length $t$)」。

    现把题解中的一些术语和定义摘录在此。

    Some conventions and symbols:All indices of strings start from zero. $|x|$ denotes length of string $x$. $ ev(x)$ stands for the reverse of string $x$. $xy$ stands for concatenation of $x$ and $y$. $x^{a}$ stands for concatenation of $a$ copies of $x$ (e.g. $x =$ 'ab', $x^2 =$ 'abab'). $x[a, b]$ stands for the substring of $x$ starting and ending from the $a$-th and $b$-th character. (e.g. 'abc'$[1, 2] =$ 'bc')
     
    Border of $x$: strings which are common prefix and suffix of $x$. Formally, $x$ has a border of length $t$ ($x[0, t - 1]$) iff $x_i = x_{|x| - t + i}$ ($0le i < t$).
    Period of $x$: $x$ has a period of length $t$ iff $x_i = x_i + t$ $(0 le i < |x| - t)$. When $tmid |x|$ we also call $t$ a full period. From the formulas it's easy to see $x$ has a period of length $t$ iff $x$ has a border of length $|x| - t$, ($ 1 le t le |x|$).

    问题转化为:求将一个字符串 $S$ 转化为某个以 $n-k$ 为周期的无限长字符串 $T$ 的子串,所需的最少更改次数。

    这个问题思考起来可比原问题清楚多了,而且至此我们已经把开头说到的两种情况统一起来了

    可以通过频数统计求解:

    分别统计

    [1, 1+n-k, 1+2(n-k), dots ]

    [2, 2+n-k, dots]

    [cdots]

    [n-k, n-k+n-k, dots]

    上A, G, C, T出现的频数,将其改成频数最大的那个字符,这样所需的总改动次数就是答案。

    P.S. 这篇随笔是我看了李舜阳hihoCoder #1052 基因工程写的。看他画的图还是不能完全把握这个问题,我觉得从数学上将问题形式化,寻找能够简化问题的必要条件,对我们分析问题极有帮助,也是一种科学的思维方式。我们即使不画图也能透彻地分析这个问题,相反只看李舜阳的图而不借助形式化的推导仍是糊里糊涂。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int MAX_N=1e3+10;
     4 char s[MAX_N];
     5 const char* item="ACGT";
     6 int main(){
     7     //freopen("in", "r", stdin);
     8     int T, K, N, rep, ans, maxi, cnt[4]; //A, C, G, T
     9     scanf("%d", &T);
    10     while(T--){
    11         scanf("%s%d", s+1, &K);
    12         N=strlen(s+1);
    13         rep=N-K;
    14         ans=0;
    15         for(int i=1; i<=rep; i++){
    16             memset(cnt, 0, sizeof(cnt));
    17             for(int j=i; j<=N; j+=rep){
    18                 for(int k=0; k<4; k++){
    19                     if(s[j]==item[k]){
    20                         cnt[k]++;
    21                         break;
    22                     }
    23                 }
    24             }
    25             maxi=0;
    26             for(int j=0; j<4; j++){
    27                 maxi=max(maxi, cnt[j]);
    28                 ans+=cnt[j];
    29             }
    30             ans-=maxi;
    31         }
    32         printf("%d
    ", ans);
    33     }
    34     return 0;
    35 }
  • 相关阅读:
    set使用
    css盒子模型详解一
    列表页调用当前栏目的子类织梦标签
    织梦如何在导航栏下拉菜单中调用当前栏目子类
    HDU1812
    BZOJ1485: [HNOI2009]有趣的数列
    组合数学学习笔记
    Full_of_Boys训练2总结
    Full_of_Boys训练1总结
    FFT算法学习笔记
  • 原文地址:https://www.cnblogs.com/Patt/p/4455834.html
Copyright © 2011-2022 走看看