P6216 回文匹配

回文匹配

/*
这里sum表示一维前缀和
sum(r-m+1) - sum(l-1)
sum(r-m+1-i) - sum(l-1+i)
所以应该是使用二位前缀和来进行处理
len/2也就是我半径需要的最小长度
有些难模拟,但是就是二维前缀和
最后统计答案的地方是真的绕
*/
#include <bits/stdc++.h>
using namespace std;
const int M=3e6+5;
#define int unsigned int
int ne[M];
void kmp(string s,int n) {
for(int i=2,j=0;i<=n;i++) {
while(j&&s[i]!=s[j+1])j=ne[j];
if(s[i]==s[j+1])j++;
ne[i]=j;
}
}
int sum[M];//二维前缀和
void find(string s,int n,string t,int m) {
for(int i=1,j=0;i<=n;i++) {
while(j&&s[i]!=t[j+1])j=ne[j];
if(s[i]==t[j+1])j++;
if(j==m) {
sum[i-j+1]=1;
j=ne[j];
}
}
}
int p[M];
void manacher(string s,int n) {
s.push_back('@');
for(int i=1,mid=0,r=0;i<=n;i++) {
if(i<=r)p[i]=min(p[2*mid-i],r-i+1);
while(s[i-p[i]]==s[i+p[i]])p[i]++;
if(i+p[i]-1>r)mid=i,r=i+p[i]-1;
}
}
signed main() {
int n,m;
cin>>n>>m;
string s1,s2;
cin>>s1>>s2;
s1=' '+s1,s2=' '+s2;
kmp(s2,m);
find(s1,n,s2,m);
for(int i=1;i<=n;i++)sum[i]+=sum[i-1];
for(int i=1;i<=n;i++)sum[i]+=sum[i-1];//二维前缀和处理
manacher(s1,n);
int ans=0;
for(int i=1;i<=n;i++) {
if(2*p[i]-1<m)continue;
int r=i+p[i]-1,l=i-p[i]+1;
l--;r=r-m+1;
int mid=(l+r)/2;
//这里很绕呀
ans+=sum[r]-sum[mid]-sum[((l+r)&1)?mid:mid-1]+sum[l==0?l:l-1];
}
cout<<ans<<endl;
return 0;
}
posted @   basicecho  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示