• Obsessive String


    Codeforces Round #282 (Div. 1)  B. Obsessive String

    题目:链接

    解题思路:

    1. 先用kmp找到所有的匹配点,时间复杂度O(n+m),n和m分别是文本和模版字符串的长度。
    2. 用dp[i]表示i是bk(题中的)时,字符串前i个字符的子串中的满足条件的总数
    3. 定义dp2[i]是前i个dp[i]的和,dp3[i]是前i个dp2[i]的和,m是匹配串的长度。
    4. 转移:当i不是匹配的结尾点时,dp[i]=dp[i-1],反之,dp[i]=dp3[i]+i-m+1;
    5. 当i不是匹配的结尾点时,只要把bk从i-1点变到i点,故数量不变,dp[i]=dp[i-1]。
    6. 而当i是匹配的结尾点时,考虑ak(题中)可以取1,2,..,i-m+1(index从1开始)
    7. 故当k=1时,有i+m-1个(当时就由于没考虑到k=1的情况要单独算,一直过不了样例)
    8. 当k大于1时,当ak取j(1<=j<=i-m+1)时,bk-1可以取1,2,...,j-1,故有dp2[j-1]
    9. 而由ak取值,故有dp3[i-m]个,故dp[i]=dp3[i]+i-m+1
    10. 最后的结果就是dp2[n-1],n为字符串长度。
    11. 注意取模
    12. 同时解题思路index是从1开始,我程序中index从0开始

    代码如下:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cmath>
     4 #include <algorithm>
     5 using namespace std;
     6 const int maxn=100010;
     7 const int mod=1e9+7;
     8 char s[maxn];
     9 char t[maxn];
    10 int f[maxn];
    11 int dp[maxn];
    12 int q[maxn];
    13 int dp2[maxn];
    14 int dp3[maxn];
    15 void getFail(char *P, int *f)
    16 {
    17     int m=strlen(P);
    18     f[0]=0;
    19     f[1]=0;
    20     for(int i=1;i<m;i++)
    21     {
    22         int j=f[i];
    23         while(j&&P[i]!=P[j])
    24         {
    25             j=f[j];
    26         }
    27         f[i+1]=P[i]==P[j]?j+1:0;
    28     }
    29 }
    30 void find(char *T,char *P,int *f)
    31 {
    32     int n=strlen(T);
    33     int m=strlen(P);
    34     getFail(P,f);
    35     int j=0;
    36     for(int i=0;i<n;i++)
    37     {
    38         while(j&&P[j]!=T[i])
    39         {
    40             j=f[j];
    41         }
    42         if(P[j]==T[i])
    43         {
    44             j++;
    45         }
    46         if(j==m)
    47         {
    48             q[i]=1;
    49         }
    50     }
    51 }
    52 
    53 
    54 int main()
    55 {
    56     while(scanf("%s%s",s,t)!=EOF)
    57     {
    58         int i;
    59         memset(q,0,sizeof(q));
    60         find(s,t,f);
    61         int n=strlen(s);
    62         int m=strlen(t);
    63         dp[0]=dp2[0]=dp3[0]=q[0];
    64         for(i=1;i<=n;i++)
    65         {
    66             if(q[i]==0)
    67             {
    68                 dp[i]=dp[i-1];
    69             }
    70             else
    71             {
    72                 dp[i]=(dp3[i-m]+i-m+2)%mod;
    73             }
    74             dp2[i]=(dp[i]+dp2[i-1])%mod;
    75             dp3[i]=(dp2[i]+dp3[i-1])%mod;
    76         }
    77         printf("%d
    ",dp2[n-1]);
    78     }
    79     
    80 
    81 
    82     return 0;
    83 }

    AC如下:

  • 相关阅读:
    设计模式(十):享元模式
    设计模式(九):装饰者模式
    设计模式(八):组合模式
    设计模式(七):桥接模式
    设计模式(六):适配器模式
    设计模式(一)工厂模式(补) -- 理解记忆方式
    [转] 本地项目上传github (新项目 / 旧项目)
    设计模式(五):外观模式
    php语言搭建nginx反向代理,负载均衡常遇到的问题
    linux tail命令用法
  • 原文地址:https://www.cnblogs.com/sunjieee/p/4164421.html
Copyright © 2020-2023  润新知