A M形字符串

A M形字符串

给一个长度为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 IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
#define pi acos(-1)
using namespace std;

const int N = 1e6 + 5;
const double eps = 1e-4;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ull mod = 1e12 + 7;
inline ull 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; }
//hs:正向哈希 hs2:反向哈希 
ull k = 1331, p, base[N], hs[N], hs2[N];
string s;
string str;
//判断是否是回文串
bool ishw(ll p) {
    if (hs[p] * base[s.size() - p + 1] + hs2[s.size() - p] == hs2[s.size()]) return true;
    return false;
}
void solve()
{
    cin >> s;
    ll ans = 1;
    hs[0] = 0;
    for (int i = 1; i <= s.size(); i++) {
        hs[i] = s[i - 1] * base[i] + hs[i - 1];
        hs2[i] = s[s.size() - i] * base[i] + hs2[i - 1];
    }
    for (int i = 2; i <= s.size(); i++) {
        if (i % 2 == 0 && ishw(i / 2)) {
            if (hs[i / 2] * base[i / 2 + 1] + hs[i / 2] == hs[i]) ans++;
        }
        else {
            if (ishw(i / 2 + 1) && hs[i / 2 + 1] * base[i / 2 + 1] + hs[i / 2] == hs[i]) ans++;
        }
    }
    cout << ans << "\n";
}

signed main()
{
    IOS;
    //init();
    ll t = 1;
    base[1] = 1;
        //预处理底数 
    for (int i = 2; i <= 1e6; i++) {
        base[i] = base[i - 1] * k;
    }
    while (t--)
        solve();
    return 0;
}

 

posted @ 2022-04-19 19:15  Yaqu  阅读(51)  评论(0)    收藏  举报