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; }