给你一个主串一个子串,然后主串中匹配到子串就可以把当前部分改为*,
问主串有多少中不同的样子。
纯dp做法。
统计种类数的话,
dp[i]={ 如果后缀串不完全匹配的话:dp[i] = dp[j-1];
如果后缀串完全匹配的话 dp[i] = dp[i - 1] + dp[i-len2];
}
#include<iostream>
#include<cstring>
#include<map>
#include<cstdio>
#include<cmath>
#include<queue>
#include<algorithm>
#include<stack>
#define mod 19999
#define INF 0x3f3f3f3f
#define bug puts("***********")
using namespace std;
long long dp[1000000];
char s1[1000000],s2[1000000];
bool judge(int index,int len){
if(index+1<len) return 0;
for(int i=0;i<len;i++){
if(s1[index-i]!=s2[len-i-1]){
return 0;
}
}
return 1;
}
int main(){
int t,n,len;
scanf("%d",&t);
for(int cas=1;cas<=t;cas++){
scanf("%s%s",s1,s2);
int len1=strlen(s1);
int len2=strlen(s2);
int sum=0;
memset(dp,0,sizeof(dp));
dp[0]=1;
for(int i=0;i<len1;i++){
dp[i+1]=dp[i];
if(judge(i,len2)){
dp[i+1]=(dp[i+1]+dp[i+1-len2])%1000000007;
}
}
printf("Case #%d: %d\n",cas,dp[len1]);
}
return 0;
}
用kmp优化的话只需要用kmp提前将每个匹配串的 最后一位的下标存入数组中去,这样就省去了dp中的每次的从头到尾的匹配了。
#include <bits/stdc++.h>
using namespace std;
#define REP(i,k,n) for(int i=k;i<n;i++)
#define REPP(i,k,n) for(int i=k;i<=n;i++)
#define scan(d) scanf("%d",&d)
#define scann(n,m) scanf("%d%d",&n,&m)
#define mst(a,k) memset(a,k,sizeof(a));
#define LL long long
#define N 100005
#define mod 1000000007
char a[1000000],b[1000000];
LL dp[100005];
int Next[N],idx[N];
void MakeNext(int m)
{
Next[0]=-1;
int i=0,j=-1;
while(i<m)
{
if(j==-1||b[i]==b[j])
{
++i,++j;
Next[i]=j;
}
else j=Next[j];
}
}
int KMP(int n,int m) //a是主串,b是模式串,n是主串长,m是模式串长
{
MakeNext(m);
int i=0,j=0,ret=0;
while(i<n)
{
if(a[i]==b[j]||j==-1)++i,++j;
else j=Next[j];
if(j==m)
{
idx[i] = 1; //各匹配到的模式串在主串中的首字母位置
j=Next[j]; //允许在主串中重叠查找
/*j=0; //不允许重叠*/
}
}
return ret; //成功匹配次数
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int t;
scan(t);
for(int cas=1;cas<=t;cas++)
{
<span style="white-space:pre"> </span>memset(idx,0,sizeof(idx));
scanf("%s%s",a,b);
int len = strlen(a);
int len2 = strlen(b);
dp[0]=1;
for(int i=1;i<=len;i++)
{
dp[i] = dp[i-1];
if(i>=len2 && idx[i-1]+idx[i-len2-1]==2))
dp[i] = ( dp[i] + dp[i-len2] ) % mod;
}
printf("Case #%d: %I64d\n",cas,dp[len]);
}
return 0;
}