pyyzDay11

落课了

模拟赛

T1

大炮

dp[i][j]表示第一个串1i和第二个串1j的位置能否匹配

扫一遍判断即可

注意前缀*的情况特判,以及初始化

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<bits/stdc++.h>
#define int long long
#define jiaa(a,b) {a+=b;if(a>=MOD) a-=MOD;}
#define jian(a,b) {a-=b;if(a<0) a+=MOD;}
using namespace std;
int ksm(int a,int b,int p){
	if(b==0) return 1;
	if(b==1) return a%p;
	int c=ksm(a,b/2,p);
	c=c*c%p;
	if(b%2==1) c=c*a%p;
	return c%p;	
}
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
map<char,bool> mm;
int dp[5005][5005],maxx[5005];
signed main()
{
	//freopen("filename.in", "r", stdin);
	//freopen("filename.out", "w", stdout);
	string S,t;
	cin>>S>>t;
	string s="";
	int N=S.size();
	int m=t.size();
	for(int i=0;i<m;i++){
		mm[t[i]]=1;
	}
	for(int j=0;j<N;j++){
		if(S[j]=='*'||S[j]=='?') continue;
		if(!mm[S[j]]){
			cout<<"NO"<<'\n';
			return 0;
		}
	}
	int fl=0;
	for(int i=0;i<N;i++){
		if(!fl&&S[i]!='*'){
			fl=1;
			s+=S[i];
		}
		else if(fl){
			s+=S[i];
		}
	}
	int n=s.size();
	if(fl){
		for(int j=0;j<m;j++){
			if(s[0]==t[j]||s[0]=='?') dp[0][j]++;
		} 
	}
	else{
		if(s[0]==t[0]||s[0]=='?') dp[0][0]++;
		else{
			cout<<"NO"<<'\n';
			return 0;
		}
	}
	for(int i=1;i<n;i++){
		for(int j=0;j<m;j++){
			if(s[i]>='a'&&s[i]<='z'){
				if(s[i]==t[j]&&dp[i-1][j-1]>0) dp[i][j]++;
			}
			else if(s[i]=='?'){
				if(dp[i-1][j-1]>0) dp[i][j]++;
			}
			else{
				if(dp[i-1][j-1]){
					dp[i][j]++;
					dp[i+1][j]++;
				}
				if(maxx[i-1]) dp[i][j]++;
			}
			maxx[i]=max(maxx[i],dp[i][j]);
		}
	}
	if(dp[n-1][m-1]>0) cout<<"YES"<<'\n';
	else cout<<"NO"<<'\n';
	return 0;
}

T2

考虑n^2暴力

枚举A|At|A两个断点

hash判断是否相等即可

考虑优化掉枚举断点

对整个字符串进行manacher预处理每个点回文最大长度

现在枚举断点i

发现A At和At A都是回文

即需要找到满足 j<=di+i且 i>=j-dj的所有j点

显然树状数组做即可

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<bits/stdc++.h>
#define int long long
#define jiaa(a,b) {a+=b;if(a>=MOD) a-=MOD;}
#define jian(a,b) {a-=b;if(a<0) a+=MOD;}
using namespace std;
int ksm(int a,int b,int p){
	if(b==0) return 1;
	if(b==1) return a%p;
	int c=ksm(a,b/2,p);
	c=c*c%p;
	if(b%2==1) c=c*a%p;
	return c%p;
}
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
#define lowbit(x) x&(-x)
int d[2000005];
const int MAXN=2000005;
int sum[MAXN];
vector<int> del[2000005];
void modify(int x,int y){
	for(int i=x;i<=MAXN;i+=lowbit(i)){
		sum[i]+=y;	
	}
}
int query(int x){
	int ans=0;
	for(int i=x;i;i-=lowbit(i)){
		ans+=sum[i];
	}
	return ans;
}
signed main()
{
	//freopen("filename.in", "r", stdin);
	//freopen("filename.out", "w", stdout);
	string s;
	string T=" *";
	cin>>s;
	int nn=s.size();
	for(int i=0;i<nn;i++){
		T+=s[i];
		T+='*';
	}
	int mid=0,r=-1;
	int n=T.size();
	int ans=0;
	for(int i=1;i<n;i++){
		if(i<r) d[i]=min(r-i+1,d[2*mid-i]);
		int x=i-d[i];
		int y=i+d[i];
		while(y<n&&x&&T[x]==T[y]){
			d[i]++;
			y++;
			x--;
		}
		if(d[i]+i-1>r){
			r=d[i]+i-1;
			mid=i;
		}
	}
	for(int i=1;i<n;i+=2){
		for(auto ed:del[i]) modify(ed,-1);
		ans-=query(i-d[i]);
		ans+=query(i);
		modify(i,1);
		del[i+d[i]+1].push_back(i);
	}
	cout<<ans<<'\n';
	return 0;
}
posted @ 2025-08-15 21:42  gbrrain  阅读(7)  评论(0)    收藏  举报