思路
二分
+ 字符串哈希
对于每次翻转,二分lcp
即可,check
函数通过字符串哈希进行哈希值快速获取,然后判断即可。
代码
# 字符串哈希
base, mod = 1331, 10**9 + 7
base_inv = pow(base,mod-2,mod)
def getPreHash(s):
n = len(s)
# hash前缀和
pre_hash = [0] * (n+1)
# 指数数组
# pow_arr[i] 代表 mul 的 i 次方
pow_arr = [0] * (n+1)
pow_arr_inv = [0] * (n+1)
# 可以使用两个mod组成二元组编码,防止hash碰撞
# 或者mod足够大。。
tmp = 0
mul = 1
mul_inv = 1
# 次方从大到小
for i in range(n):
tmp = (tmp * base + ord(s[i])) % mod
pre_hash[i+1] = tmp
pow_arr[i] = mul
pow_arr_inv[i] = mul_inv
mul = mul * base % mod
mul_inv = mul_inv * base_inv % mod
pow_arr[n] = mul
pow_arr_inv[n] = mul_inv
return pre_hash,pow_arr,pow_arr_inv
# 获取[l,r)的hashcode值,长度为r-l
def getHash(pre_hash,pow_arr,l,r):
return ((pre_hash[r] - pre_hash[l] * pow_arr[r-l])%mod + mod)%mod
for _ in range(int(input().strip())):
n = int(input())
s = input().strip()
t = input().strip()
pre_hash_s,_,_ = getPreHash(s)
pre_hash_t,pow_arr,pow_arr_inv = getPreHash(t)
maxt = 0
pos = 1
# 前i个字符反转
# 反向滚动哈希,小到大
tmp = 0
mul = 1
pre_hash = [0]
for i in range(n):
tmp += ord(s[i]) * mul
tmp %= mod
mul *= base
mul %= mod
pre_hash.append(tmp)
# 二分
start = 1
end = n
while start <= end:
l = (start + end) // 2
# 在翻转长度内
if l <= i + 1:
# 逆元
p = (tmp - pre_hash[i+1-l]) * pow_arr_inv[i+1-l]
# 超过翻转长度
else:
p = tmp * pow_arr[l-i-1] + getHash(pre_hash_s,pow_arr,i+1,l)
p %= mod
if p == getHash(pre_hash_t,pow_arr,0,l):
start = l + 1
else:
end = l - 1
start -= 1
if maxt < start:
maxt = start
pos = i + 1
print(maxt,pos)