1 条题解

  • 0
    @ 2025-4-16 16:33:02

    可以明显看出,瑕疵回文串包含了普通回文串。

    首先,我们可以预处理前缀哈希数组 hs[i]hs[i] 和后缀哈希数组 sh[i]sh[i] ,然后结合二分法和前后缀字符串哈希,在 O(nlogn)O(nlogn) 时间复杂度下求得每个下标作为中心时,最长回文串的区间 [l,r][l,r]

    在求出回文串的基础上,我们进一步使用二分法来确定瑕疵字符的长度,使得在区间 hs[l2len,l2]hs[l-2-len,l-2] 处的哈希值与在区间 sh[r+2,r+2+len]sh[r+2,r+2+len] 处的哈希值相等。

    最终,答案可以表示为: ans=(rl+1)+(len+1)2ans=(r-l+1)+(len+1)*2

    在二分过程中需要注意避免越界问题。

    时间复杂度:O(nlogn)O(nlogn)

    const int maxn = 2e5 + 7, p = 131;
    int n;
    string s;
    
    unsigned int hs[maxn], sh[maxn], qy[maxn];
    unsigned int get1(int l, int r)
    {
    	return hs[r] - hs[l - 1] * qy[r - l + 1];
    }
    
    unsigned int get2(int l, int r)
    {
    	return sh[l] - sh[r + 1] * qy[r - l + 1];
    }
    
    bool check(int l1, int r1, int l2, int r2)
    {
    	if (l2 <= 0 || r1 > n)
    		return false;
    
    	return get1(l1, r1) == get2(l2, r2);
    }
    
    void solve()
    {
    	cin >> n >> s;
    
    	qy[0] = 1;
    	for (int i = 1; i <= n; i++)
    	{
    		qy[i] = qy[i - 1] * p;
    		hs[i] = hs[i - 1] * p + s[i - 1] - 'a';
    	}
    	for (int i = n; i >= 1; i--)
    		sh[i] = sh[i + 1] * p + s[i - 1] - 'a';
    
    	int ans = 0;
    	for (int i = 1; i <= n; i++)
    	{
    		int l = 0, r = n;
    		while (l < r)
    		{
    			int mid = (l + r + 1) / 2;
    			if (check(i, i + mid, i - mid, i))
    				l = mid;
    			else
    				r = mid - 1;
    		}
    
    		int tmp = l;
    		if (i + (tmp + 1) <= n && i - (tmp + 1) > 0)
    			tmp++;
    
    		l = 0, r = n;
    		while (l < r)
    		{
    			int mid = (l + r + 1) / 2;
    			if (check(i + tmp + 1, i + tmp + mid, i - tmp - mid, i - tmp - 1))
    				l = mid;
    			else
    				r = mid - 1;
    		}
    
    		ans = max(ans, 1 + (tmp + l) * 2);
    	}
    
    	for (int i = 1; i < n; i++)
    	{
    		int l = 0, r = n;
    		while (l < r)
    		{
    			int mid = (l + r + 1) / 2;
    			if (check(i + 1, i + mid, i + 1 - mid, i))
    				l = mid;
    			else
    				r = mid - 1;
    		}
    		int tmp = l;
    		if (i + (tmp + 1) <= n && i + 1 - (tmp + 1) > 0)
    			tmp++;
    
    		l = 0, r = n;
    		while (l < r)
    		{
    			int mid = (l + r + 1) / 2;
    			if (check(i + tmp + 1, i + tmp + mid, i + 1 - tmp - mid, i - tmp))
    				l = mid;
    			else
    				r = mid - 1;
    		}
    
    		ans = max(ans, (tmp + l) * 2);
    	}
    
    	cout << ans << endl;
    }
    
    • 1

    信息

    ID
    5
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者