登录—专业IT笔试面试备考平台_牛客网(题目链接)
题目描述
给一个长度为n的字符串(1<=n<=200000),他只包含小写字母
找到这个字符串多少个前缀是M形字符串.
M形字符串定义如下:
他由两个相同的回文串拼接而来,第一个回文串的结尾字符和第二个字符串的开始字符可以重叠,也就是以下都是M形字符串.
abccbaabccba(由abccba+abccba组成)
abcbaabcba(有abcba+abcba组成)
abccbabccba(由abccba+abccba组成组成,但是中间的1是共用的)
a(一个单独字符
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define db long double
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
#define pi acos(-1)
#define gcd(a, b) __gcd(a,b)
#define lcm(a, b) a/gcd(a,b)*b
#define pii pair<int, int>
using namespace std;
const int N = 2e5 + 5;
const double eps = 1e-4;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
inline ll qpow(ll x, ll y, ll M) { ll ans = 1; while (y) { if (y & 1)ans = ans * x % M; x = x * x % M; y = y >> 1; }return ans % M; }
ll h1[N], h2[N], pp[N], n;
string s;
bool check1(ll l, ll r)//检查长度为r的前缀是否为回文串
{
if (r % 2 == 1)//当前缀长度是偶数是,中间字符可以无视
{
ll x = r / 2;
l = n - r + 1;
r = n - x - 1;
if (h1[x] == ((h2[r] - h2[l - 1] * pp[r - l + 1]) % mod + mod) % mod)
return true;
}
else
{
ll x = r / 2;
l = n - r + 1;
r = n - x;//长度为偶数时没有中间字符,和奇数判断唯一的区别
if (h1[x] == ((h2[r] - h2[l - 1] * pp[r - l + 1]) % mod + mod) % mod)
return true;
}
return false;
}
bool check2(ll l, ll r)//检查第一种情况,不重叠
{
if (r * 2 - 1 <= n && h1[r] == ((h1[2 * r - 1] - h1[r - 1] * pp[r]) % mod + mod) % mod)
return true;
return false;
}
bool check3(ll l, ll r)//检查第二种情况,有一个字符重叠
{
if (r * 2 <= n && h1[r] == ((h1[2 * r] - h1[r] * pp[r]) % mod + mod) % mod)
return true;
return false;
}
void solve()
{
cin >> s;
n = s.size();
ll p = 233;
s = " " + s;
pp[0] = 1;
for (ll i = 1; i <= n; i++)
pp[i] = pp[i - 1] * p % mod;
for (ll i = 1; i <= n; i++)
h1[i] = (h1[i - 1] * p + s[i]) % mod;//正哈希
for (ll i = n; i >= 1; i--)
h2[n - i + 1] = (h2[n - i] * p + s[i]) % mod;//反哈希,用来判断是否为回文串
ll ans = 0;
for (ll i = 1; i <= n; i++)
{
if (check1(1, i))
{
if (check2(1, i))
ans++;
if (check3(1, i))
ans++;
}
}
cout << ans << '\n';
}
int main()
{
ll t = 1;
//cin >> t;
while (t--)
solve();
return 0;
}
也算)