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