题目大意:
给你
N(N<=30)
个串,第
i
个串由
然后再给你一个串
S
,其中
解题思路:
首先我们从
1∼N
依次处理每一个串。
对于每个串,我们维护几个量,我们用
AC[i]
表示第
i
个串中出现了多少个
然后我们对于计算串
i
的时候,从头到尾扫一遍,中间记录一个
注意:此题要高精度。
AC代码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
int N;
char S[110]="\0";
int Lm=0,Ls=0;
int change[40][600]={{0}};
int next[110]={0};
char st[40][10010]={"\0"},en[40][10010]={"\0"};
const int Mod=100000000;
struct gjd_
{
int cnmbdctr[1000];
}Len[40],AC[40];
inline struct gjd_ operator + (struct gjd_ a1,int a2)
{
struct gjd_ bb=a1;
bb.cnmbdctr[1]+=a2;
for(register int i=1;i<=bb.cnmbdctr[0];i++)
{
if(bb.cnmbdctr[i]>=Mod)
bb.cnmbdctr[i+1]+=bb.cnmbdctr[i]/Mod,bb.cnmbdctr[i]%=Mod;
else break;
if(i==bb.cnmbdctr[0]) bb.cnmbdctr[0]++;
}
return bb;
}
inline struct gjd_ operator + (struct gjd_ a1,struct gjd_ a2)
{
struct gjd_ bb=a1;
bb.cnmbdctr[0]=max(a1.cnmbdctr[0],a2.cnmbdctr[0]);
for(register int i=1;i<=bb.cnmbdctr[0];i++)
{
bb.cnmbdctr[i]+=a2.cnmbdctr[i];
if(bb.cnmbdctr[i]>=Mod)
{
bb.cnmbdctr[i+1]+=bb.cnmbdctr[i]/Mod,bb.cnmbdctr[i]%=Mod;
if(i==bb.cnmbdctr[0]) bb.cnmbdctr[0]++;
}
}
return bb;
}
inline void prt(struct gjd_ a1)
{
for(int i=a1.cnmbdctr[0];a1.cnmbdctr[i]==0 && a1.cnmbdctr[0]>1;a1.cnmbdctr[0]--);
printf("%d",a1.cnmbdctr[a1.cnmbdctr[0]]);
for(register int i=a1.cnmbdctr[0]-1;i>=1;i--)
printf("%08d",a1.cnmbdctr[i]);
puts("");
return;
}
bool operator ==(struct gjd_ a1,int a2)
{
if(a1.cnmbdctr[0]==1 && a1.cnmbdctr[1]==a2)
return true;
return false;
}
bool operator <(struct gjd_ a1,int a2)
{
if(a1.cnmbdctr[0]==1 && a1.cnmbdctr[1]<a2)
return true;
return false;
}
bool operator >=(struct gjd_ a1,int a2)
{
if(a1.cnmbdctr[0]>1 || a1.cnmbdctr[1]>=a2)
return true;
return false;
}
void read(char *chh)
{
char c='\0';
int len=0;
c=getchar();
for(;c==' ' || c=='\n' || c=='\r';c=getchar());
for(;c!=' ' && c!='\n' && c!='\r' && c!='\0' && c!=-1;c=getchar())
chh[++len]=c;
return;
}
void Pre()
{
Ls=strlen(S+1);
next[1]=0;
for(int i=2;i<=Ls;i++)
{
for(int j=next[i-1];;j=next[j])
{
if(S[j+1]==S[i])
{
next[i]=j+1;
break;
}
else if(j==0)
{
next[i]=0;
break;
}
}
}
return;
}
void KMP(struct gjd_ &ans,char mom[])
{
int now=0;
Lm=strlen(mom+1);
for(int i=1;i<=Lm;i++)
{
for(;;)
{
if(mom[i]==S[now+1])
{
now++;
break;
}
if(now==0)
break;
else now=next[now];
}
if(now==Ls)
{
now=next[now];
ans=ans+1;
}
}
return;
}
void geten(int cnt,char now[])
{
if(strlen(now+1)>=Ls)
memcpy(en[cnt]+1,now+strlen(now+1)-Ls+2,sizeof(char)*(Ls-1));
else memcpy(en[cnt],now,sizeof(en[cnt]));
return;
}
void done(int cnt)
{
char str[10010]="\0";
int sp=0;
int flag1=0;
for(int i=1;i<=change[cnt][0];i++)
{
if(change[cnt][i]=='a' || change[cnt][i]=='b')
{
str[++sp]=change[cnt][i];
Len[cnt]=Len[cnt]+1;
str[sp+1]='\0';
if(Len[cnt]==Ls-1 && flag1==0)
{
memcpy(st[cnt],str,sizeof(str));
flag1=1;
}
if(i==change[cnt][0])
geten(cnt,str);
}
else
{
Len[cnt]=Len[cnt]+Len[change[cnt][i]];
strcat(str+1,st[change[cnt][i]]+1);
if(Len[change[cnt][i]]<Ls)
{
sp=strlen(str+1);
if(Len[cnt]>=Ls-1 && flag1==0)
{
memcpy(st[cnt],str,sizeof(char)*Ls);
flag1=1;
}
if(i==change[cnt][0])
geten(cnt,str);
}
else
{
AC[cnt]=AC[cnt]+AC[change[cnt][i]];
if(Len[cnt]>=Ls-1 && flag1==0)
{
memcpy(st[cnt],str,sizeof(char)*Ls);
flag1=1;
}
KMP(AC[cnt],str);
sp=Ls-1;
memcpy(str,en[change[cnt][i]],sizeof(str));
if(i==change[cnt][0])
geten(cnt,str);
}
}
}
if(flag1==0)
memcpy(st[cnt],str,sizeof(char)*Ls);
KMP(AC[cnt],str);
return;
}
int main()
{
scanf("%d\n",&N);
scanf("%s",S+1);
Pre();
for(int i=0;i<40;i++)
AC[i].cnmbdctr[0]=Len[i].cnmbdctr[0]=1;
for(int p=1;p<=N;p++)
{
int num;
scanf("%d",&num);
int len=0;
for(int i=1;i<=num;i++)
{
char ch[10]="\0";
read(ch);
if(ch[1]>='0' && ch[1]<='9')
{
int x=0;
for(int j=1;ch[j]>='0' && ch[j]<='9';j++)
x=x*10+ch[j]-'0';
change[p][++len]=x;
}
else change[p][++len]=(int)ch[1];
}
change[p][0]=num;
done(p);
}
prt(AC[N]);
return 0;
}