智算之道初赛第二场 字符串

智算之道初赛第二场 字符串

题目链接

给定两个字符串 S 和 T,它们都只由小写字母组成。现在请计算出字符串 S 的本质不同的排列中有多少种是字符串 T 的子串。

本质不同,就是看起来不同,例如 aab 有 33 种本质不同的排列 aab, aba, baa。

输入格式

第一行有一个字符串 S
第二行有一个字符串 T

输出格式

输出一个整数表示字符串 S 的本质不同的排列中有多少种是字符串 T 的子串

数据规模与约定

对于 30% 的数据, 1 ≤ ∣ S ∣ ≤ 5 , 1 ≤ ∣ T ∣ ≤ 200 1 \leq |S| \leq 5, 1 \leq |T| \leq 200 1S5,1T200
对于 %60% 的数据, 1 ≤ ∣ S ∣ ≤ 2000 , 1 ≤ ∣ T ∣ ≤ 2000 1 \leq |S| \leq 2000, 1 \leq |T| \leq2000 1S2000,1T2000
对于 %100% 的数据, 1 ≤ ∣ S ∣ ≤ 200000 , 1 ≤ ∣ T ∣ ≤ 200000 1 \leq |S| \leq 200000,1 \leq |T| \leq 200000 1S200000,1T200000

样例输入

aab
abacabaa

样例输出

2

直接截取判断 T 串的每一个长为 l e n ( S ) len(S) len(S) 的子串即可,这里有一个卡时间的点就是只有和 S 串匹配的串才截取(用两个数组判断即可),否则每次判断都截取会 T,AC代码如下:

#include
using namespace std;
typedef long long ll;
int cnt1[26]={0},cnt2[26]={0};
bool cmp(){
    for(int i=0;i<26;i++){
        if(cnt1[i]!=cnt2[i]) return 0;
    }
    return 1;
}
int main(){
    string s,t;
    set<string>ans;
    cin>>s>>t;
    int n1=s.size(),n2=t.size();
    for(int i=0;i<n1;i++){
        cnt1[s[i]-'a']++;
        cnt2[t[i]-'a']++;
    }
    if(cmp()) ans.insert(t.substr(0,n1));
    for(int i=n1;i<n2;i++){
        cnt2[t[i-n1]-'a']--;
        cnt2[t[i]-'a']++;
        if(cmp()){
            ans.insert(t.substr(i-n1+1,n1));
        }
    }
    cout<<ans.size();
    return 0;
}

你可能感兴趣的:(string,字符串)