打字机
本题看起来很不好做,但仔细画画图找找规律之后还是能找出规律的
——————————————————————————————————————————————
现在已知以
s
[
i
]
s[i]
s[i]结尾的答案
s
u
m
[
i
]
sum[i]
sum[i]和总答案,
这时候一个准备加进答案的
d
o
t
h
[
j
]
doth[j]
doth[j]
那么我们发现,总答案的两倍减去
s
u
m
[
i
]
sum[i]
sum[i]
证明:原来的答案中有以
d
o
t
h
[
j
]
结
尾
的
,
也
有
不
以
d
o
t
h
[
j
]
结
尾
的
,
因
为
每
个
字
母
都
有
可
能
没
打
到
,
则
有
s
u
m
[
d
o
t
h
[
j
]
]
个
不
以
d
o
t
h
[
j
]
结
尾
的
,
即
d
o
t
h
[
j
]
没
打
到
。
而
这
时
候
在
所
有
的
方
案
后
加
上
d
o
t
h
[
i
]
,
因
为
有
可
能
打
到
,
也
有
可
能
没
打
到
,
所
以
乘
2
,
而
又
因
为
s
u
m
[
d
o
t
h
[
j
]
]
个
答
案
已
算
过
,
所
以
应
减
去
doth[j]结尾的,也有不以doth[j]结尾的,因为每个字母都有可能没打到,则有sum[doth[j]]个不以doth[j]结尾的,即doth[j]没打到。而这时候在所有的方案后加上doth[i],因为有可能打到,也有可能没打到,所以乘2,而又因为sum[doth[j]]个答案已算过,所以应减去
doth[j]结尾的,也有不以doth[j]结尾的,因为每个字母都有可能没打到,则有sum[doth[j]]个不以doth[j]结尾的,即doth[j]没打到。而这时候在所有的方案后加上doth[i],因为有可能打到,也有可能没打到,所以乘2,而又因为sum[doth[j]]个答案已算过,所以应减去
遇到退格,
if(cnt){
sum[s[cnt]-'A'+1]++;
ans=(ans+1)%mod;
cnt--;
}
因为在doth中加字母实际上就是没达到字母的方案,已经算过,所以不用管,而原数组中的s[i]是没算过的,所以要加1,而因为退格会对后面贡献新的方案,所以sum要+1
#include<bits/stdc++.h>
using namespace std;
const int N=5000010,mod=0x125E591;
char s[N],doth[N];
int n,m,sum[N];
int main(){
scanf("%d%d",&n,&m);
int cnt=n,ans=1;
scanf("%s %s",(s+1),(doth+1));
for(int i=1;i<=m;i++)
{
if((doth[i]!='u')){
int tmp=sum[doth[i]-'A'+1];
sum[doth[i]-'A'+1]=ans;
ans=((ans*2%mod-tmp%mod)%mod+mod)%mod;
}
else{
if(cnt){
sum[s[cnt]-'A'+1]++;
ans=(ans+1)%mod;
cnt--;
}
}
}
printf("%lld",ans);
}