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),然后也有可能自己组成一个新的独立的串,那么就要让F[i]+=L。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<iostream>
 5 #include<algorithm>
 6 char s[200005],t[200005];
 7 int len1,len2,f[200005],sum[200005],p[1200005],pd[200005];
 8 const int Mod=1000000007;
 9 int read(){
10     int t=0,f=1;char ch=getchar();
11     while (ch<‘0‘||ch>‘9‘){if (ch==‘-‘) f=-1;ch=getchar();}
12     while (‘0‘<=ch&&ch<=‘9‘){t=t*10+ch-‘0‘;ch=getchar();}
13     return t*f;
14 }
15 void kmp(){
16     p[1]=0;int j=0;
17     for (int i=2;i<=len2;i++){
18         while (j>0&&t[j+1]!=t[i]) j=p[j];
19         if (t[j+1]==t[i]) j++;
20         p[i]=j;
21     }
22     j=0;
23     for (int i=1;i<=len1;i++){
24         while (j>0&&t[j+1]!=s[i]) j=p[j];
25         if (t[j+1]==s[i])j++;
26         if (j==len2){
27             pd[i]=i-len2+1;
28         }
29     }
30     for (int i=1;i<=len1;i++)
31      if (!pd[i]) pd[i]=pd[i-1];
32 }
33 int main(){
34     scanf("%s",s+1);scanf("%s",t+1);
35     len1=strlen(s+1);len2=strlen(t+1);
36     kmp();
37     for (int i=1;i<=len1;i++){
38         f[i]=f[i-1];
39         int l=pd[i];
40         if (!l) continue;
41         (f[i]+=(sum[l-1]+l)%Mod)%=Mod;
42         sum[i]=(sum[i-1]+f[i])%Mod;
43     }
44     printf("%d\n",f[len1]);
45 }
时间: 2024-10-23 17:45:58

Codeforces 494B Obsessive String的相关文章

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] =

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的最大标号,固定了右侧位

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 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找出

codeforces 825F F. String Compression dp+kmp找字符串的最小循环节

/** 题目:F. String Compression 链接:http://codeforces.com/problemset/problem/825/F 题意:压缩字符串后求最小长度. 思路: dp[i]表示前i个字符需要的最小次数. dp[i] = min(dp[j]+w(j+1,i)); (0<=j<i); [j+1,i]如果存在循环节(自身不算),那么取最小的循环节x.w = digit((i-j)/x)+x; 否则w = i-j+1; 求一个区间最小循环节: 证明:http://w

Codeforces 827E Rusty String - 快速傅里叶变换 - 暴力

Grigory loves strings. Recently he found a metal strip on a loft. The strip had length n and consisted of letters "V" and "K". Unfortunately, rust has eaten some of the letters so that it's now impossible to understand which letter was

CodeForces 545B Equidistant String (模拟)

[题目链接]:click here~~ [题目大意]: 题意:求一个字符串,使得它与S,T,相似度相差相等. [思路]:就是找出S,T之间的相差个数,相差为奇数,输出impossible.输出为偶数的话不同的前半部分输出S后半部分输出T就好了. 代码: /* * Problem: CodeForces 545B * Running time: 0MS * Complier: G++ * Author: herongwei * Create Time: 8:11 2015/9/17 星期四 */

codeforces 128 B. String 优先队列

链接:http://codeforces.com/contest/128/problem/B B. String time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output One day in the IT lesson Anna and Maria learned about the lexicographic order. Stri

Codeforces 778A:String Game(二分暴力)

http://codeforces.com/problemset/problem/778/A 题意:给出字符串s和字符串p,还有n个位置,每一个位置代表删除s串中的第i个字符,问最多可以删除多少个字符使得s串依旧包含p串. 思路:想到二分,以为二分做法依旧很暴力.但是别人的做法确实就是二分暴力搞啊. 枚举删除字符数,然后判断的时候如果s串包含p串,那么可以往右区间找,否则左区间找. 1 #include <bits/stdc++.h> 2 using namespace std; 3 #def