玛雅文字

玛雅文字

**文件名:**mayan.in / mayan.out
题目描述

解读玛雅文字向来不简单,因为单词中的字母顺序可以是任意排列的。今天,科研团队找到了你来解决一个简化过的问题——在给定的一段玛雅文字 S 中,求出给定的单词 T 出现了几次,并保证 S 和 T 均由大小写字母构成。

限制

1s 32M

1≤|T|≤ 3000,|T|≤|S|≤ 3,000,000

输入格式

第一行,两个整数,表示 |T| 和 |S|

第二行,一个字符串 T

第三行,一个字符串 S

输出格式

一个整数,表示出现的次数

输入样例

4 11

cAda

AbrAcadAbRa

输出样例

2

样例解释

子串 Acad 和 cadA 均是 cAda 的排列,因此一共出现了 2 次。

题解

维护 |S| 中所有长度为 |T| 的区间里,每种字母的出现次数,维护这与实际次数一致的字母个数,每次修改至多 2 种字母,因此可以线性扫描计数。

#include <bits/stdc++.h>
using namespace std;
template <typename T> void read(T &t) {
    char ch=getchar(); int f=1; t=0;
    while ('0'>ch||ch>'9') { if (ch=='-') f=-1; ch=getchar(); }
    do { (t*=10)+=ch-'0'; ch=getchar(); } while ('0'<=ch&&ch<='9'); t*=f;
}
typedef long long ll;
const int maxn=(3e6)+10;
int n,m,c1[60],c2[60],cnt,ans;
char s1[maxn],s2[maxn];
int f(char ch) {
    if ('a'<=ch&&ch<='z') return ch-'a'+1;
    return ch-'A'+27;
}
int main() {
    read(n); read(m);
    scanf("%s %s",s1+1,s2+1);
    for (int i=1;i<=n;i++)
        c1[f(s1[i])]++;
    for (int i=1;i<=n;i++)
        c2[f(s2[i])]++;
    for (int i=1;i<=52;i++)
        if (c1[i]==c2[i]) cnt++;
    if (cnt==52) ans++;
    for (int i=n+1;i<=m;i++) {
        int tmp=c2[f(s2[i])];
        c2[f(s2[i])]++;
        if (tmp==c1[f(s2[i])]) cnt--;
        else if (c2[f(s2[i])]==c1[f(s2[i])]) cnt++;
        tmp=c2[f(s2[i-n])];
        c2[f(s2[i-n])]--;
        if (tmp==c1[f(s2[i-n])]) cnt--;
        else if (c2[f(s2[i-n])]==c1[f(s2[i-n])]) cnt++;
        if (cnt==52) ans++;
    }
    printf("%d\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值