2020智算之道初赛第一场 - 高校组 C.字符串

C.字符串

题目链接-C.字符串
在这里插入图片描述
在这里插入图片描述解题思路

  • 如果字符串 s s s的长度大于字符串 t t t的长度,那么 s s s的任何排列都不可能是 t t t的子串,直接输出 0 0 0即可
  • 因为要求 s s s的不同排列有多少种是 t t t的子串,将 s s s的不同排列全部求出来肯定会超时,我们可以直接计算 s s s中每个字母的个数,那么 t t t中如果有子串中各个字符个数与 s s s相同则说明是该子串是 s s s的一种排列
  • t t t中满足条件的子串可能会有排列相同的情况,这时我们就可以将每个满足条件的子串放入set容器中去重,最后输出set中元素个数即可
  • i>=x-1时,我们可以先判断当前位置的字母 t i t_i ti的数目是否与字符串 s s s相同,如果当前位置的字母都不满足条件那么就没有继续判断其他字母的必要,类似于一个剪枝操作
  • 记得删除过期元素 t i − t t_{i-t} tit(b[t[i-x]-'a']--),其实就是滑动窗口问题,维护一个长度为s.length()的子串,类似于单调队列求解问题
  • 具体操作见代码

附上代码

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
#define lowbit(x) (x &(-x))
#define endl '\n'
using namespace std;
const int INF=0x3f3f3f3f;
const int dir[4][2]={-1,0,1,0,0,-1,0,1};
const double PI=acos(-1.0);
const double e=exp(1.0);
const double eps=1e-10;
const int M=1e9+7;
const int N=2e5+10;
typedef long long ll;
typedef pair<int,int> PII;
typedef unsigned long long ull;
string s,t;
set<string> st;
int a[30],b[30];
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);

	cin>>s>>t;
	int x=s.length();
	int y=t.length();
	if(x>y){
		cout<<0<<endl;
		return 0;
	}
	for(int i=0;i<x;i++)
		a[s[i]-'a']++;
	for(int i=0;i<y;i++){
		b[t[i]-'a']++;
		if(i>=x-1){
			if(i!=x-1) b[t[i-x]-'a']--;
			if(b[t[i]-'a']==a[t[i]-'a']){
				bool ass=0;
				for(char j='a';j<='z';j++){
					if(b[j-'a']!=a[j-'a']){
						ass=1;
						break;
					}
				}
				if(!ass)
					st.insert(t.substr(i-x+1,x));
			}
		}
	}
	cout<<st.size()<<endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值