几道用到KMP的DP题:
hdu 5763 hdu 3689 hdu 3336 codeforces 494B codevs 3945
关于KMP的nx数组:
如果在本文中看见了nx[]指的是所谓“成功指针”,或者getnx()函数跟本人之前的板子写的不一样......
都是因为求nx数组有两种方法!!!
详情请阅本人的另一篇文章:关于KMP算法的重大发现
好了我们进入正题~
一道一道来~
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 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define mod 1000000007 5 using namespace std; 6 7 int t,al,bl; 8 char a[100005]; 9 char b[100005]; 10 int nx[100005]; 11 int fl[100005]; 12 int f[100005]; 13 14 void getnx() 15 { 16 nx[1]=0; 17 for(int i=2,j=1;i<=bl;) 18 { 19 nx[i]=j; 20 while(j&&b[j]!=b[i])j=nx[j]; 21 j++,i++; 22 } 23 } 24 25 void kmp() 26 { 27 for(int i=1,j=1;i<=al;) 28 { 29 while(j&&b[j]!=a[i])j=nx[j]; 30 if(j==bl) 31 { 32 fl[i]=1; 33 j=nx[j]; 34 } 35 else j++,i++; 36 } 37 } 38 39 int main() 40 { 41 scanf("%d",&t); 42 for(int cs=1;cs<=t;cs++) 43 { 44 memset(a,0,sizeof(a)); 45 memset(b,0,sizeof(b)); 46 memset(fl,0,sizeof(fl)); 47 scanf("%s",a+1); 48 scanf("%s",b+1); 49 al=strlen(a+1); 50 bl=strlen(b+1); 51 getnx(); 52 kmp(); 53 f[0]=1; 54 for(int i=1;i<=al;i++) 55 { 56 if(fl[i])f[i]=(f[i-1]+f[i-bl])%mod; 57 else f[i]=f[i-1]; 58 } 59 printf("Case #%d: %d\n",cs,f[al]); 60 } 61 return 0; 62 }