判定回文串-暴力、字符串哈希算法

问题描述

给定一个长度为 n 的字符串 S,再给定 q 组查询,每组查询给定一个 l,r,询问 sl∼r 是否是回文串。若是,输出 Yes,否则输出 No

输入格式

第一行输入二个正整数 n,q,表示字符串的长度与查询数。(1≤n≤5000,1≤q≤106)。

接下来一行输入一个字符串 S。

接下来 q 行,每行输入两个正整数 l,r。(1≤l≤r≤n)

保证 S 为小写字母构成,且字符串索引从 1 开始。

输出格式

对于每组查询,给定一个 l,r,询问 sl∼r 是否是回文串。若是,输出 Yes,否则输出 No

样例输入

5 3
abcba
1 5
1 3
2 4

样例输出

Yes
No
Yes

运行限制

语言最大运行时间最大运行内存
C++1s256M
C1s256M
Java2s256M
Python33s256M
PyPy33s256M
Go3s256M
JavaScript3s256M

 方法一:暴力

通过循环判断两端的字符是否相同,向中间靠拢。

#include<iostream>
#include<cmath>
#include<iostream>
#include<cstring>
#include<string>
#include<list>
using namespace std;
typedef long long ll;
const ll MAX = 1e5+4;
int main()
{
    ll n, q;
    cin >> n >> q;
    string s;
    cin >> s;
    for (int i = 1; i <= q; i++)
    {
        ll l, r,f=0;
        cin >> l >> r;
        while (l<=r)
        {
            if (s[l - 1] != s[r - 1])
            {
                f = 1;
                break;
            }
            l++;
            r--;
        }
        if (f == 1)
        {
            cout << "No" << endl;
        }
        else cout << "Yes" << endl;
    }
    return 0;
}

方法二:字符串哈希算法 

 

 不同字符串,哈希值也不相同,判断回文时,只要从左到右的哈希值等于从右向左的哈希值,即回文。

#include<iostream>
#include<cmath>
#include<iostream>
#include<cstring>
#include<string>
#include<list>
using namespace std;
typedef long long ll;
const ll MAX = 1e4+4;
const ll P = 131;
const ll M = 1e9 + 7;
ll H1[MAX], H2[MAX];
ll p[MAX] = {1};
void init(string s)
{
	for (int i = 0; i < s.size(); i++)//前缀和
	{
		H1[i + 1] = (H1[i] * P % M + (s[i] - 'a' + 1)) % M;
		p[i + 1] = p[i] * P%M;
	}
	for (int i = s.size() - 1; i >= 0; i--)//后缀和
	{
		H2[s.size()-i]= (H2[s.size() - i-1] * P % M + (s[i] - 'a' + 1)) % M;
	}
}
bool get_substr(ll l, ll r,ll s)
{
	ll h1 = (H1[r] - H1[l - 1] * p[r - l + 1])%M;
	if (h1 < 0)
	{
		h1 += M;
	}
	ll h2 = (H2[s-l+1] - H2[s-r] * p[r - l + 1])%M;
	if (h2 < 0)
	{
		h2 += M;
	}
	return h1 == h2;
}
int main()
{
	ll n, q;
	cin >> n >> q;
	string s;
	cin >> s;
	init(s);
	for (int i = 1; i <= q; i++)
	{
		ll l, r;
		cin >> l >> r;
		if (get_substr(l,r,(ll)s.size()))
		{
			cout << "Yes" << endl;
		}
		else cout << "No" << endl;
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值