ISIJ 2018 玛雅文字

ISIJ 2018 玛雅文字(Training Round D5T1)

无忧公主 2018-07-10

题目名称:玛雅文字

**文件名:**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;
}

猜你喜欢

转载自blog.csdn.net/xyc1719/article/details/81744848