链接
题意
给 你 两 个 串 s 和 t , 翻 转 一 次 s 串 的 一 个 区 间 [ l , r ] , 问 有 多 少 对 l , r 使 得 翻 转 后 的 s 串 等 于 t 串 。 给你两个串s和t,翻转一次s串的一个区间[l,r],问有多少对l,r使得翻转后的s串等于t串。 给你两个串s和t,翻转一次s串的一个区间[l,r],问有多少对l,r使得翻转后的s串等于t串。
题解
s
=
t
时
,
a
n
s
=
s
串
中
回
文
个
数
,
可
由
M
a
n
a
c
h
e
r
算
法
求
得
。
s=t时,ans=s串中回文个数,可由Manacher算法求得。
s=t时,ans=s串中回文个数,可由Manacher算法求得。
s
≠
t
时
,
找
出
最
左
最
右
的
不
等
坐
标
l
、
r
,
先
判
断
区
间
[
l
,
r
]
翻
转
后
s
、
t
串
是
否
相
等
,
不
相
等
则
无
解
;
s \not = t时,找出最左最右的不等坐标l、r,先判断区间[l,r]翻转后s、t串是否相等,不相等则无解;
s=t时,找出最左最右的不等坐标l、r,先判断区间[l,r]翻转后s、t串是否相等,不相等则无解;
相
等
的
话
就
将
l
、
r
向
外
扩
展
,
看
是
否
一
致
。
a
n
s
=
扩
展
次
数
+
1
相等的话就将l、r向外扩展,看是否一致。ans=扩展次数+1
相等的话就将l、r向外扩展,看是否一致。ans=扩展次数+1
代码
#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
#define ll long long
void manacher(char *str,ll *hw);
string s,t;
char str[5006000];
ll hw[5006000];
ll n,T,l,r,ans,f;
int main(){
cin>>T;
while(T--)
{
cin>>s>>t;
l=r=-1;
ans=0;
n=s.size();
for(int i=0;i<n;i++)
{
if(s[i]!=t[i])
{
l=i;
break;
}
str[i]=s[i];
}
if(l==-1)
{
manacher(str,hw);
for(int i=0;i<n;i++)ans+=hw[i]/2;
}
else
{
for(int i=n-1;i>=0;i--)
{
if(s[i]!=t[i])
{
r=i;
break;
}
}
f=1;
for(int i=l;i<=r;i++)
{
if(s[i]!=t[l+r-i])
{
f=0;
break;
}
}
if(f)
{
while(l>=0&&r<n)
{
if(s[l]!=t[r])break;
l--;r++;ans++;
}
}
}
cout<<ans<<endl;
}
return 0;
}
void change(char *str)
{
str[0]=str[1]='#';
for(int i=0; i<n; i++)
{
str[i*2+2]=s[i];
str[i*2+3]='#';
}
n=n*2+2;
str[n]=0;
}
void manacher(char *str,ll *hw)
{
change(str);
int maxright=0,mid;
for(int i=1; i<n; i++)
{
if(i<maxright)
hw[i]=min(hw[(mid<<1)-i],hw[mid]+mid-i);
else
hw[i]=1;
for(; str[i+hw[i]]==str[i-hw[i]]; ++hw[i]);
if(hw[i]+i>maxright)
{
maxright=hw[i]+i;
mid=i;
}
}
}