Obsessive String

本文详细阐述了Codeforces Round #282(Div.1) B.ObsessiveString 的解题策略,包括使用KMP算法寻找匹配点,动态规划方法计算满足条件的子串总数,并提供了通过代码实现的具体步骤。
摘要由CSDN通过智能技术生成

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\n",dp2[n-1]);
78     }
79     
80 
81 
82     return 0;
83 }

 

AC如下:

转载于:https://www.cnblogs.com/sunjieee/p/4164421.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值