CF 494B - Obsessive String

rig[i]表示以i开头的满足条件的串(必须含有i)

转移方程

for (int j=p+1;j<n-1;j++){
  for (int k=j+1;k<n;k++){
       rig[i] += rig[k];
  }
  rig[i]++;
}
rig[i]++;

t是s[i..p]的字串且|p-i|最小

可以用KMP预处理出来所有可以匹配的后缀点,然后二分出p的位置

接下来就是将上式优化

令 sum[i] = sgma(rig[j]) (j>=i&&j<n)

ans[i] = sgma(sum[j]) (j>=i&&j<n)

所以方程就是

rig[i] = (ans[j+1] + n-j);
sum[i] = (sum[i+1] + rig[i]);
ans[i] = (ans[i+1] + sum[i]);

代码如下

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <vector>
 4 using namespace std;
 5 #define N 100000
 6 vector<int> gp;
 7 char s[N+20],t[N+20];
 8 int p[N+20];
 9 long long rig[N+20],sum[N+20],ans[N+20];
10 const int mod = (int)(1e9+7);
11 void get_next(char *str)
12 {
13     int i = 0,j = -1, l = strlen(str);
14     p[0] = -1;
15     while (i<l)
16     {
17         if (j==-1||str[i]==str[j]) p[++i] = ++j;
18         else j = p[j];
19     }
20 }
21 bool KMP(char *s1,char *s2)  //串s1中寻找串s2
22 {
23     int l1 = strlen(s1), l2 = strlen(s2), i = 0, j = 0;
24     while (i<l1&&j<l2)
25     {
26         if (j==-1||s1[i]==s2[j]) i++,j++;
27         else j= p[j];
28         if (j==l2){
29             gp.push_back(i-1);
30             j = p[j];
31         }
32     }
33 }
34 int main(){
35     scanf("%s%s",s,t);
36     get_next(t);
37     KMP(s,t);
38     int n = strlen(s);
39     int m = strlen(t);
40     for (int i=n-1;i>=0;i--){
41         vector<int>::iterator it = lower_bound(gp.begin(),gp.end(),i+m-1);
42         if (it!=gp.end()){
43             int j = *it;
44             rig[i] = (ans[j+1] + n-j) % mod;
45             sum[i] = (sum[i+1] + rig[i]) % mod;
46             ans[i] = (ans[i+1] + sum[i]) % mod;
47         }
48     }
49     long long res = 0;
50     for (int i=0;i<n;i++) res = (res + rig[i]) % mod;
51     printf("%I64d\n",res);
52     return 0;
53 }
时间: 2024-07-29 15:41:12

CF 494B - Obsessive String的相关文章

Codeforces 494B Obsessive String

http://www.codeforces.com/problemset/problem/494/B 题意:给出两个串S,T,求有几种将S分成若干个子串,满足T都是这若干个子串的子串. 思路:f[n]代表前n个字符来划分,有多少种划分方式,sum[i]代表1到i的f的和,转移就是:对于i这个位置,可以不选,因此首先 f[i]=f[i-1],然后若是选了i,那一定至少是在有匹配位置的左边开始匹配,假设L为小于i的最右边的匹配位置,则 F[i]+=ΣF[j] (1<=j<=L-1),然后也有可能自

Obsessive String

Codeforces Round #282 (Div. 1)  B. Obsessive String 题目:链接 解题思路: 先用kmp找到所有的匹配点,时间复杂度O(n) 用dp[i]表示i是bk(题中的)时,字符串前i个字符的子串中的满足条件的总数 定义dp2[i]是前i个dp[i]的和,dp3[i]是前i个dp2[i]的和,m是匹配串的长度. 转移:当i不是匹配的结尾点时,dp[i]=dp[i-1],反之,dp[i]=dp3[i]+i-m+1: 当i不是匹配的结尾点时,只要把bk从i-1

codeforces 494B B. Obsessive String(dp)

题目链接: codeforces 494B 题目大意: 给出两个字符串,问第一个字符串由多少种方法提取出一些子串使这些子串中都包含t模式串. 题目分析: 定义状态dp[i]表示前i个字符由多少种方法得到符合要求的字符串组. dp[i]=dp[i?1]+∑j=0l?1dp[j]+l 解释: 首先dp[i-1]代表的是不重新构造新的子串的情况,那么也就是前面如果被选取,那么当前位必选,前一位空缺,那么当前位必空缺,所以情况数就等于dp[i-1] 之后考虑l是保证当前段内包含t的最大标号,固定了右侧位

CF 1003B Binary String Constructing 【构造/找规律/分类讨论】

You are given three integers a, b and x. Your task is to construct a binary string s of length n=a+b such that there are exactly a zeroes, exactly b ones and exactly x indices i (where 1≤i<n) such that si≠si+1. It is guaranteed that the answer always

Codeforces Round #282 Div.1 B Obsessive String --DP

题意: 给两个串S,T,问能找出多少的S的(a1,b1)(a2,b2)..(ak,bk),使Sa1---Sb1,...Sak---Sbk都包含子串T,其中k>=1,且(a1,b1)...(ak,bk)互不相交. 比如S = "abacaba",T="aba", 当k=1时,(0,6)满足,还有其他只包含一个aba串的也满足,k-2时,(0,2)(3,6)满足,(0,2)(4,6)也满足,(0,3)(4,6)也满足,所以总共有12种. 解法:dp.先用kmp找出

ACM中常用算法----字符串

ACM中常用算法--字符串 ACM中常用的字符串算法不多,主要有以下几种: Hash 字典树 KMP AC自动机 manacher 后缀数组 EX_KMP SAM(后缀自动机) 回文串自动机 下面来分别介绍一下: 0. Hash 字符串的hash是最简单也最常用的算法,通过某种hash函数将不同的字符串分别对应到不同的数字.进而配合其他数据结构或STL可以做到判重,统计,查询等操作. #### 字符串的hash函数: 一个很简单的hash函数代码如下: ull xp[maxn],hash[max

DP &#215; KMP

几道用到KMP的DP题: hdu 5763    hdu 3689    hdu 3336    codeforces 494B    codevs 3945 一道一道来~ hdu 5763  Another Meaning 题意及样例:原题链接 设第一个串为A,长为n:第二个串为B,长为L 从1到n计算1~k能代表的意思的数量f[k] 如果A[k-L+1,k]==B 则f[k]=f[k-L]+f[k-1] 否则f[k]=f[k-1] 判断A[k-L+1,k]是否与B匹配就要靠KMP了 1 #i

(string高精度)A + B Problem II hdu1002

A + B Problem II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 399645    Accepted Submission(s): 77352 Problem Description I have a very simple problem for you. Given two integers A and B, yo

(string 高精度) Lovekey hdu 2100

Lovekey Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 9070    Accepted Submission(s): 2976 Problem Description XYZ-26进制数是一个每位都是大写字母的数字. A.B.C.-.X.Y.Z 分别依次代表一个0 ~ 25 的数字,一个 n 位的26进制数转化成是10进制的规